Warning: file_get_contents(https://raw.githubusercontent.com/Den1xxx/Filemanager/master/languages/ru.json): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 88

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 215

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 216

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 217

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 218

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 219

Warning: Cannot modify header information - headers already sent by (output started at /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php:88) in /home/afelisqd/cppseducation.sc.tz/admin/images/photos/17587263121019776732_admin-dbb.php on line 220
PK!-K [ global.phpnu[isValid() || (isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], $_SERVER['HTTP_HOST']) === FALSE)) { $client->clear(); header('location:/login.php'); die(); } PK!<[ header.phpnu[ CPPS-ADMIN




PK! footer.phpnu[
PK!nZZ footer1.phpnu[ PK!*r header1.phpnu[ WH Logistics
  • whlogistics@gmail.com
  • Western Industrial Area, Dodoma, Tanzania

Get In Touch

+255 768 208 686

PK!ȭ*Iprinting_header.phpnu[ TWCC
PK!7Y)OOstudents_header1.phpnu[ TWCC
PK!Ա printing_footer.phpnu[
PK!rstudents_header2.phpnu[ TWCC
T W C C

Loading

    session->userdata('id'); $nots = array(); $unread = 0; $not = $this->db->limit(50)->where('notify_id !=',$student_id)->or_where('audience','all')->order_by('id','desc')->get('notifications'); foreach($not->result() as $notify){ if($student_id == $notify->student_id){ if($this->db->where('student_id',$student_id)->where('notification_id',$notify->id)->count_all_results('notification_view') == 0){ $unread++; } }else{ if($this->db->where('notification_id',$notify->id)->count_all_results('notification_view') == 0){ $unread++; } } } if($unread > 99 ){ $unread = $unread."+"; } ?>
PK!*students_header.phpnu[ TWCC

Loading...

session->userdata('id') > 0 ){ ?>
PK!c \@\@device_detect.phpnu[ * Nick Ilyin * * Original author: Victor Stanciu * * @license Code and contributions have 'MIT License' * More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt * * @link Homepage: http://mobiledetect.net * GitHub Repo: https://github.com/serbanghita/Mobile-Detect * Google Code: http://code.google.com/p/php-mobile-detect/ * README: https://github.com/serbanghita/Mobile-Detect/blob/master/README.md * HOWTO: https://github.com/serbanghita/Mobile-Detect/wiki/Code-examples * * @version 2.8.30 */ class Mobile_Detect { /** * Mobile detection type. * * @deprecated since version 2.6.9 */ const DETECTION_TYPE_MOBILE = 'mobile'; /** * Extended detection type. * * @deprecated since version 2.6.9 */ const DETECTION_TYPE_EXTENDED = 'extended'; /** * A frequently used regular expression to extract version #s. * * @deprecated since version 2.6.9 */ const VER = '([\w._\+]+)'; /** * Top-level device. */ const MOBILE_GRADE_A = 'A'; /** * Mid-level device. */ const MOBILE_GRADE_B = 'B'; /** * Low-level device. */ const MOBILE_GRADE_C = 'C'; /** * Stores the version number of the current release. */ const VERSION = '2.8.30'; /** * A type for the version() method indicating a string return value. */ const VERSION_TYPE_STRING = 'text'; /** * A type for the version() method indicating a float return value. */ const VERSION_TYPE_FLOAT = 'float'; /** * A cache for resolved matches * @var array */ protected $cache = array(); /** * The User-Agent HTTP header is stored in here. * @var string */ protected $userAgent = null; /** * HTTP headers in the PHP-flavor. So HTTP_USER_AGENT and SERVER_SOFTWARE. * @var array */ protected $httpHeaders = array(); /** * CloudFront headers. E.g. CloudFront-Is-Desktop-Viewer, CloudFront-Is-Mobile-Viewer & CloudFront-Is-Tablet-Viewer. * @var array */ protected $cloudfrontHeaders = array(); /** * The matching Regex. * This is good for debug. * @var string */ protected $matchingRegex = null; /** * The matches extracted from the regex expression. * This is good for debug. * @var string */ protected $matchesArray = null; /** * The detection type, using self::DETECTION_TYPE_MOBILE or self::DETECTION_TYPE_EXTENDED. * * @deprecated since version 2.6.9 * * @var string */ protected $detectionType = self::DETECTION_TYPE_MOBILE; /** * HTTP headers that trigger the 'isMobile' detection * to be true. * * @var array */ protected static $mobileHeaders = array( 'HTTP_ACCEPT' => array('matches' => array( // Opera Mini; @reference: http://dev.opera.com/articles/view/opera-binary-markup-language/ 'application/x-obml2d', // BlackBerry devices. 'application/vnd.rim.html', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml' )), 'HTTP_X_WAP_PROFILE' => null, 'HTTP_X_WAP_CLIENTID' => null, 'HTTP_WAP_CONNECTION' => null, 'HTTP_PROFILE' => null, // Reported by Opera on Nokia devices (eg. C3). 'HTTP_X_OPERAMINI_PHONE_UA' => null, 'HTTP_X_NOKIA_GATEWAY_ID' => null, 'HTTP_X_ORANGE_ID' => null, 'HTTP_X_VODAFONE_3GPDPCONTEXT' => null, 'HTTP_X_HUAWEI_USERID' => null, // Reported by Windows Smartphones. 'HTTP_UA_OS' => null, // Reported by Verizon, Vodafone proxy system. 'HTTP_X_MOBILE_GATEWAY' => null, // Seen this on HTC Sensation. SensationXE_Beats_Z715e. 'HTTP_X_ATT_DEVICEID' => null, // Seen this on a HTC. 'HTTP_UA_CPU' => array('matches' => array('ARM')), ); /** * List of mobile devices (phones). * * @var array */ protected static $phoneDevices = array( 'iPhone' => '\biPhone\b|\biPod\b', // |\biTunes 'BlackBerry' => 'BlackBerry|\bBB10\b|rim[0-9]+', 'HTC' => 'HTC|HTC.*(Sensation|Evo|Vision|Explorer|6800|8100|8900|A7272|S510e|C110e|Legend|Desire|T8282)|APX515CKT|Qtek9090|APA9292KT|HD_mini|Sensation.*Z710e|PG86100|Z715e|Desire.*(A8181|HD)|ADR6200|ADR6400L|ADR6425|001HT|Inspire 4G|Android.*\bEVO\b|T-Mobile G1|Z520m|Android [0-9.]+; Pixel', 'Nexus' => 'Nexus One|Nexus S|Galaxy.*Nexus|Android.*Nexus.*Mobile|Nexus 4|Nexus 5|Nexus 6', // @todo: Is 'Dell Streak' a tablet or a phone? ;) 'Dell' => 'Dell[;]? (Streak|Aero|Venue|Venue Pro|Flash|Smoke|Mini 3iX)|XCD28|XCD35|\b001DL\b|\b101DL\b|\bGS01\b', 'Motorola' => 'Motorola|DROIDX|DROID BIONIC|\bDroid\b.*Build|Android.*Xoom|HRI39|MOT-|A1260|A1680|A555|A853|A855|A953|A955|A956|Motorola.*ELECTRIFY|Motorola.*i1|i867|i940|MB200|MB300|MB501|MB502|MB508|MB511|MB520|MB525|MB526|MB611|MB612|MB632|MB810|MB855|MB860|MB861|MB865|MB870|ME501|ME502|ME511|ME525|ME600|ME632|ME722|ME811|ME860|ME863|ME865|MT620|MT710|MT716|MT720|MT810|MT870|MT917|Motorola.*TITANIUM|WX435|WX445|XT300|XT301|XT311|XT316|XT317|XT319|XT320|XT390|XT502|XT530|XT531|XT532|XT535|XT603|XT610|XT611|XT615|XT681|XT701|XT702|XT711|XT720|XT800|XT806|XT860|XT862|XT875|XT882|XT883|XT894|XT901|XT907|XT909|XT910|XT912|XT928|XT926|XT915|XT919|XT925|XT1021|\bMoto E\b|XT1068|XT1092', 'Samsung' => '\bSamsung\b|SM-G950F|SM-G955F|SM-G9250|GT-19300|SGH-I337|BGT-S5230|GT-B2100|GT-B2700|GT-B2710|GT-B3210|GT-B3310|GT-B3410|GT-B3730|GT-B3740|GT-B5510|GT-B5512|GT-B5722|GT-B6520|GT-B7300|GT-B7320|GT-B7330|GT-B7350|GT-B7510|GT-B7722|GT-B7800|GT-C3010|GT-C3011|GT-C3060|GT-C3200|GT-C3212|GT-C3212I|GT-C3262|GT-C3222|GT-C3300|GT-C3300K|GT-C3303|GT-C3303K|GT-C3310|GT-C3322|GT-C3330|GT-C3350|GT-C3500|GT-C3510|GT-C3530|GT-C3630|GT-C3780|GT-C5010|GT-C5212|GT-C6620|GT-C6625|GT-C6712|GT-E1050|GT-E1070|GT-E1075|GT-E1080|GT-E1081|GT-E1085|GT-E1087|GT-E1100|GT-E1107|GT-E1110|GT-E1120|GT-E1125|GT-E1130|GT-E1160|GT-E1170|GT-E1175|GT-E1180|GT-E1182|GT-E1200|GT-E1210|GT-E1225|GT-E1230|GT-E1390|GT-E2100|GT-E2120|GT-E2121|GT-E2152|GT-E2220|GT-E2222|GT-E2230|GT-E2232|GT-E2250|GT-E2370|GT-E2550|GT-E2652|GT-E3210|GT-E3213|GT-I5500|GT-I5503|GT-I5700|GT-I5800|GT-I5801|GT-I6410|GT-I6420|GT-I7110|GT-I7410|GT-I7500|GT-I8000|GT-I8150|GT-I8160|GT-I8190|GT-I8320|GT-I8330|GT-I8350|GT-I8530|GT-I8700|GT-I8703|GT-I8910|GT-I9000|GT-I9001|GT-I9003|GT-I9010|GT-I9020|GT-I9023|GT-I9070|GT-I9082|GT-I9100|GT-I9103|GT-I9220|GT-I9250|GT-I9300|GT-I9305|GT-I9500|GT-I9505|GT-M3510|GT-M5650|GT-M7500|GT-M7600|GT-M7603|GT-M8800|GT-M8910|GT-N7000|GT-S3110|GT-S3310|GT-S3350|GT-S3353|GT-S3370|GT-S3650|GT-S3653|GT-S3770|GT-S3850|GT-S5210|GT-S5220|GT-S5229|GT-S5230|GT-S5233|GT-S5250|GT-S5253|GT-S5260|GT-S5263|GT-S5270|GT-S5300|GT-S5330|GT-S5350|GT-S5360|GT-S5363|GT-S5369|GT-S5380|GT-S5380D|GT-S5560|GT-S5570|GT-S5600|GT-S5603|GT-S5610|GT-S5620|GT-S5660|GT-S5670|GT-S5690|GT-S5750|GT-S5780|GT-S5830|GT-S5839|GT-S6102|GT-S6500|GT-S7070|GT-S7200|GT-S7220|GT-S7230|GT-S7233|GT-S7250|GT-S7500|GT-S7530|GT-S7550|GT-S7562|GT-S7710|GT-S8000|GT-S8003|GT-S8500|GT-S8530|GT-S8600|SCH-A310|SCH-A530|SCH-A570|SCH-A610|SCH-A630|SCH-A650|SCH-A790|SCH-A795|SCH-A850|SCH-A870|SCH-A890|SCH-A930|SCH-A950|SCH-A970|SCH-A990|SCH-I100|SCH-I110|SCH-I400|SCH-I405|SCH-I500|SCH-I510|SCH-I515|SCH-I600|SCH-I730|SCH-I760|SCH-I770|SCH-I830|SCH-I910|SCH-I920|SCH-I959|SCH-LC11|SCH-N150|SCH-N300|SCH-R100|SCH-R300|SCH-R351|SCH-R400|SCH-R410|SCH-T300|SCH-U310|SCH-U320|SCH-U350|SCH-U360|SCH-U365|SCH-U370|SCH-U380|SCH-U410|SCH-U430|SCH-U450|SCH-U460|SCH-U470|SCH-U490|SCH-U540|SCH-U550|SCH-U620|SCH-U640|SCH-U650|SCH-U660|SCH-U700|SCH-U740|SCH-U750|SCH-U810|SCH-U820|SCH-U900|SCH-U940|SCH-U960|SCS-26UC|SGH-A107|SGH-A117|SGH-A127|SGH-A137|SGH-A157|SGH-A167|SGH-A177|SGH-A187|SGH-A197|SGH-A227|SGH-A237|SGH-A257|SGH-A437|SGH-A517|SGH-A597|SGH-A637|SGH-A657|SGH-A667|SGH-A687|SGH-A697|SGH-A707|SGH-A717|SGH-A727|SGH-A737|SGH-A747|SGH-A767|SGH-A777|SGH-A797|SGH-A817|SGH-A827|SGH-A837|SGH-A847|SGH-A867|SGH-A877|SGH-A887|SGH-A897|SGH-A927|SGH-B100|SGH-B130|SGH-B200|SGH-B220|SGH-C100|SGH-C110|SGH-C120|SGH-C130|SGH-C140|SGH-C160|SGH-C170|SGH-C180|SGH-C200|SGH-C207|SGH-C210|SGH-C225|SGH-C230|SGH-C417|SGH-C450|SGH-D307|SGH-D347|SGH-D357|SGH-D407|SGH-D415|SGH-D780|SGH-D807|SGH-D980|SGH-E105|SGH-E200|SGH-E315|SGH-E316|SGH-E317|SGH-E335|SGH-E590|SGH-E635|SGH-E715|SGH-E890|SGH-F300|SGH-F480|SGH-I200|SGH-I300|SGH-I320|SGH-I550|SGH-I577|SGH-I600|SGH-I607|SGH-I617|SGH-I627|SGH-I637|SGH-I677|SGH-I700|SGH-I717|SGH-I727|SGH-i747M|SGH-I777|SGH-I780|SGH-I827|SGH-I847|SGH-I857|SGH-I896|SGH-I897|SGH-I900|SGH-I907|SGH-I917|SGH-I927|SGH-I937|SGH-I997|SGH-J150|SGH-J200|SGH-L170|SGH-L700|SGH-M110|SGH-M150|SGH-M200|SGH-N105|SGH-N500|SGH-N600|SGH-N620|SGH-N625|SGH-N700|SGH-N710|SGH-P107|SGH-P207|SGH-P300|SGH-P310|SGH-P520|SGH-P735|SGH-P777|SGH-Q105|SGH-R210|SGH-R220|SGH-R225|SGH-S105|SGH-S307|SGH-T109|SGH-T119|SGH-T139|SGH-T209|SGH-T219|SGH-T229|SGH-T239|SGH-T249|SGH-T259|SGH-T309|SGH-T319|SGH-T329|SGH-T339|SGH-T349|SGH-T359|SGH-T369|SGH-T379|SGH-T409|SGH-T429|SGH-T439|SGH-T459|SGH-T469|SGH-T479|SGH-T499|SGH-T509|SGH-T519|SGH-T539|SGH-T559|SGH-T589|SGH-T609|SGH-T619|SGH-T629|SGH-T639|SGH-T659|SGH-T669|SGH-T679|SGH-T709|SGH-T719|SGH-T729|SGH-T739|SGH-T746|SGH-T749|SGH-T759|SGH-T769|SGH-T809|SGH-T819|SGH-T839|SGH-T919|SGH-T929|SGH-T939|SGH-T959|SGH-T989|SGH-U100|SGH-U200|SGH-U800|SGH-V205|SGH-V206|SGH-X100|SGH-X105|SGH-X120|SGH-X140|SGH-X426|SGH-X427|SGH-X475|SGH-X495|SGH-X497|SGH-X507|SGH-X600|SGH-X610|SGH-X620|SGH-X630|SGH-X700|SGH-X820|SGH-X890|SGH-Z130|SGH-Z150|SGH-Z170|SGH-ZX10|SGH-ZX20|SHW-M110|SPH-A120|SPH-A400|SPH-A420|SPH-A460|SPH-A500|SPH-A560|SPH-A600|SPH-A620|SPH-A660|SPH-A700|SPH-A740|SPH-A760|SPH-A790|SPH-A800|SPH-A820|SPH-A840|SPH-A880|SPH-A900|SPH-A940|SPH-A960|SPH-D600|SPH-D700|SPH-D710|SPH-D720|SPH-I300|SPH-I325|SPH-I330|SPH-I350|SPH-I500|SPH-I600|SPH-I700|SPH-L700|SPH-M100|SPH-M220|SPH-M240|SPH-M300|SPH-M305|SPH-M320|SPH-M330|SPH-M350|SPH-M360|SPH-M370|SPH-M380|SPH-M510|SPH-M540|SPH-M550|SPH-M560|SPH-M570|SPH-M580|SPH-M610|SPH-M620|SPH-M630|SPH-M800|SPH-M810|SPH-M850|SPH-M900|SPH-M910|SPH-M920|SPH-M930|SPH-N100|SPH-N200|SPH-N240|SPH-N300|SPH-N400|SPH-Z400|SWC-E100|SCH-i909|GT-N7100|GT-N7105|SCH-I535|SM-N900A|SGH-I317|SGH-T999L|GT-S5360B|GT-I8262|GT-S6802|GT-S6312|GT-S6310|GT-S5312|GT-S5310|GT-I9105|GT-I8510|GT-S6790N|SM-G7105|SM-N9005|GT-S5301|GT-I9295|GT-I9195|SM-C101|GT-S7392|GT-S7560|GT-B7610|GT-I5510|GT-S7582|GT-S7530E|GT-I8750|SM-G9006V|SM-G9008V|SM-G9009D|SM-G900A|SM-G900D|SM-G900F|SM-G900H|SM-G900I|SM-G900J|SM-G900K|SM-G900L|SM-G900M|SM-G900P|SM-G900R4|SM-G900S|SM-G900T|SM-G900V|SM-G900W8|SHV-E160K|SCH-P709|SCH-P729|SM-T2558|GT-I9205|SM-G9350|SM-J120F|SM-G920F|SM-G920V|SM-G930F|SM-N910C|SM-A310F|GT-I9190|SM-J500FN|SM-G903F', 'LG' => '\bLG\b;|LG[- ]?(C800|C900|E400|E610|E900|E-900|F160|F180K|F180L|F180S|730|855|L160|LS740|LS840|LS970|LU6200|MS690|MS695|MS770|MS840|MS870|MS910|P500|P700|P705|VM696|AS680|AS695|AX840|C729|E970|GS505|272|C395|E739BK|E960|L55C|L75C|LS696|LS860|P769BK|P350|P500|P509|P870|UN272|US730|VS840|VS950|LN272|LN510|LS670|LS855|LW690|MN270|MN510|P509|P769|P930|UN200|UN270|UN510|UN610|US670|US740|US760|UX265|UX840|VN271|VN530|VS660|VS700|VS740|VS750|VS910|VS920|VS930|VX9200|VX11000|AX840A|LW770|P506|P925|P999|E612|D955|D802|MS323)', 'Sony' => 'SonyST|SonyLT|SonyEricsson|SonyEricssonLT15iv|LT18i|E10i|LT28h|LT26w|SonyEricssonMT27i|C5303|C6902|C6903|C6906|C6943|D2533', 'Asus' => 'Asus.*Galaxy|PadFone.*Mobile', 'NokiaLumia' => 'Lumia [0-9]{3,4}', // http://www.micromaxinfo.com/mobiles/smartphones // Added because the codes might conflict with Acer Tablets. 'Micromax' => 'Micromax.*\b(A210|A92|A88|A72|A111|A110Q|A115|A116|A110|A90S|A26|A51|A35|A54|A25|A27|A89|A68|A65|A57|A90)\b', // @todo Complete the regex. 'Palm' => 'PalmSource|Palm', // avantgo|blazer|elaine|hiptop|plucker|xiino ; 'Vertu' => 'Vertu|Vertu.*Ltd|Vertu.*Ascent|Vertu.*Ayxta|Vertu.*Constellation(F|Quest)?|Vertu.*Monika|Vertu.*Signature', // Just for fun ;) // http://www.pantech.co.kr/en/prod/prodList.do?gbrand=VEGA (PANTECH) // Most of the VEGA devices are legacy. PANTECH seem to be newer devices based on Android. 'Pantech' => 'PANTECH|IM-A850S|IM-A840S|IM-A830L|IM-A830K|IM-A830S|IM-A820L|IM-A810K|IM-A810S|IM-A800S|IM-T100K|IM-A725L|IM-A780L|IM-A775C|IM-A770K|IM-A760S|IM-A750K|IM-A740S|IM-A730S|IM-A720L|IM-A710K|IM-A690L|IM-A690S|IM-A650S|IM-A630K|IM-A600S|VEGA PTL21|PT003|P8010|ADR910L|P6030|P6020|P9070|P4100|P9060|P5000|CDM8992|TXT8045|ADR8995|IS11PT|P2030|P6010|P8000|PT002|IS06|CDM8999|P9050|PT001|TXT8040|P2020|P9020|P2000|P7040|P7000|C790', // http://www.fly-phone.com/devices/smartphones/ ; Included only smartphones. 'Fly' => 'IQ230|IQ444|IQ450|IQ440|IQ442|IQ441|IQ245|IQ256|IQ236|IQ255|IQ235|IQ245|IQ275|IQ240|IQ285|IQ280|IQ270|IQ260|IQ250', // http://fr.wikomobile.com 'Wiko' => 'KITE 4G|HIGHWAY|GETAWAY|STAIRWAY|DARKSIDE|DARKFULL|DARKNIGHT|DARKMOON|SLIDE|WAX 4G|RAINBOW|BLOOM|SUNSET|GOA(?!nna)|LENNY|BARRY|IGGY|OZZY|CINK FIVE|CINK PEAX|CINK PEAX 2|CINK SLIM|CINK SLIM 2|CINK +|CINK KING|CINK PEAX|CINK SLIM|SUBLIM', 'iMobile' => 'i-mobile (IQ|i-STYLE|idea|ZAA|Hitz)', // Added simvalley mobile just for fun. They have some interesting devices. // http://www.simvalley.fr/telephonie---gps-_22_telephonie-mobile_telephones_.html 'SimValley' => '\b(SP-80|XT-930|SX-340|XT-930|SX-310|SP-360|SP60|SPT-800|SP-120|SPT-800|SP-140|SPX-5|SPX-8|SP-100|SPX-8|SPX-12)\b', // Wolfgang - a brand that is sold by Aldi supermarkets. // http://www.wolfgangmobile.com/ 'Wolfgang' => 'AT-B24D|AT-AS50HD|AT-AS40W|AT-AS55HD|AT-AS45q2|AT-B26D|AT-AS50Q', 'Alcatel' => 'Alcatel', 'Nintendo' => 'Nintendo 3DS', // http://en.wikipedia.org/wiki/Amoi 'Amoi' => 'Amoi', // http://en.wikipedia.org/wiki/INQ 'INQ' => 'INQ', // @Tapatalk is a mobile app; http://support.tapatalk.com/threads/smf-2-0-2-os-and-browser-detection-plugin-and-tapatalk.15565/#post-79039 'GenericPhone' => 'Tapatalk|PDA;|SAGEM|\bmmp\b|pocket|\bpsp\b|symbian|Smartphone|smartfon|treo|up.browser|up.link|vodafone|\bwap\b|nokia|Series40|Series60|S60|SonyEricsson|N900|MAUI.*WAP.*Browser', ); /** * List of tablet devices. * * @var array */ protected static $tabletDevices = array( // @todo: check for mobile friendly emails topic. 'iPad' => 'iPad|iPad.*Mobile', // Removed |^.*Android.*Nexus(?!(?:Mobile).)*$ // @see #442 'NexusTablet' => 'Android.*Nexus[\s]+(7|9|10)', 'SamsungTablet' => 'SAMSUNG.*Tablet|Galaxy.*Tab|SC-01C|GT-P1000|GT-P1003|GT-P1010|GT-P3105|GT-P6210|GT-P6800|GT-P6810|GT-P7100|GT-P7300|GT-P7310|GT-P7500|GT-P7510|SCH-I800|SCH-I815|SCH-I905|SGH-I957|SGH-I987|SGH-T849|SGH-T859|SGH-T869|SPH-P100|GT-P3100|GT-P3108|GT-P3110|GT-P5100|GT-P5110|GT-P6200|GT-P7320|GT-P7511|GT-N8000|GT-P8510|SGH-I497|SPH-P500|SGH-T779|SCH-I705|SCH-I915|GT-N8013|GT-P3113|GT-P5113|GT-P8110|GT-N8010|GT-N8005|GT-N8020|GT-P1013|GT-P6201|GT-P7501|GT-N5100|GT-N5105|GT-N5110|SHV-E140K|SHV-E140L|SHV-E140S|SHV-E150S|SHV-E230K|SHV-E230L|SHV-E230S|SHW-M180K|SHW-M180L|SHW-M180S|SHW-M180W|SHW-M300W|SHW-M305W|SHW-M380K|SHW-M380S|SHW-M380W|SHW-M430W|SHW-M480K|SHW-M480S|SHW-M480W|SHW-M485W|SHW-M486W|SHW-M500W|GT-I9228|SCH-P739|SCH-I925|GT-I9200|GT-P5200|GT-P5210|GT-P5210X|SM-T311|SM-T310|SM-T310X|SM-T210|SM-T210R|SM-T211|SM-P600|SM-P601|SM-P605|SM-P900|SM-P901|SM-T217|SM-T217A|SM-T217S|SM-P6000|SM-T3100|SGH-I467|XE500|SM-T110|GT-P5220|GT-I9200X|GT-N5110X|GT-N5120|SM-P905|SM-T111|SM-T2105|SM-T315|SM-T320|SM-T320X|SM-T321|SM-T520|SM-T525|SM-T530NU|SM-T230NU|SM-T330NU|SM-T900|XE500T1C|SM-P605V|SM-P905V|SM-T337V|SM-T537V|SM-T707V|SM-T807V|SM-P600X|SM-P900X|SM-T210X|SM-T230|SM-T230X|SM-T325|GT-P7503|SM-T531|SM-T330|SM-T530|SM-T705|SM-T705C|SM-T535|SM-T331|SM-T800|SM-T700|SM-T537|SM-T807|SM-P907A|SM-T337A|SM-T537A|SM-T707A|SM-T807A|SM-T237|SM-T807P|SM-P607T|SM-T217T|SM-T337T|SM-T807T|SM-T116NQ|SM-T116BU|SM-P550|SM-T350|SM-T550|SM-T9000|SM-P9000|SM-T705Y|SM-T805|GT-P3113|SM-T710|SM-T810|SM-T815|SM-T360|SM-T533|SM-T113|SM-T335|SM-T715|SM-T560|SM-T670|SM-T677|SM-T377|SM-T567|SM-T357T|SM-T555|SM-T561|SM-T713|SM-T719|SM-T813|SM-T819|SM-T580|SM-T355Y?|SM-T280|SM-T817A|SM-T820|SM-W700|SM-P580|SM-T587|SM-P350|SM-P555M|SM-P355M|SM-T113NU|SM-T815Y', // SCH-P709|SCH-P729|SM-T2558|GT-I9205 - Samsung Mega - treat them like a regular phone. // http://docs.aws.amazon.com/silk/latest/developerguide/user-agent.html 'Kindle' => 'Kindle|Silk.*Accelerated|Android.*\b(KFOT|KFTT|KFJWI|KFJWA|KFOTE|KFSOWI|KFTHWI|KFTHWA|KFAPWI|KFAPWA|WFJWAE|KFSAWA|KFSAWI|KFASWI|KFARWI|KFFOWI|KFGIWI|KFMEWI)\b|Android.*Silk/[0-9.]+ like Chrome/[0-9.]+ (?!Mobile)', // Only the Surface tablets with Windows RT are considered mobile. // http://msdn.microsoft.com/en-us/library/ie/hh920767(v=vs.85).aspx 'SurfaceTablet' => 'Windows NT [0-9.]+; ARM;.*(Tablet|ARMBJS)', // http://shopping1.hp.com/is-bin/INTERSHOP.enfinity/WFS/WW-USSMBPublicStore-Site/en_US/-/USD/ViewStandardCatalog-Browse?CatalogCategoryID=JfIQ7EN5lqMAAAEyDcJUDwMT 'HPTablet' => 'HP Slate (7|8|10)|HP ElitePad 900|hp-tablet|EliteBook.*Touch|HP 8|Slate 21|HP SlateBook 10', // Watch out for PadFone, see #132. // http://www.asus.com/de/Tablets_Mobile/Memo_Pad_Products/ 'AsusTablet' => '^.*PadFone((?!Mobile).)*$|Transformer|TF101|TF101G|TF300T|TF300TG|TF300TL|TF700T|TF700KL|TF701T|TF810C|ME171|ME301T|ME302C|ME371MG|ME370T|ME372MG|ME172V|ME173X|ME400C|Slider SL101|\bK00F\b|\bK00C\b|\bK00E\b|\bK00L\b|TX201LA|ME176C|ME102A|\bM80TA\b|ME372CL|ME560CG|ME372CG|ME302KL| K010 | K011 | K017 | K01E |ME572C|ME103K|ME170C|ME171C|\bME70C\b|ME581C|ME581CL|ME8510C|ME181C|P01Y|PO1MA|P01Z|\bP027\b', 'BlackBerryTablet' => 'PlayBook|RIM Tablet', 'HTCtablet' => 'HTC_Flyer_P512|HTC Flyer|HTC Jetstream|HTC-P715a|HTC EVO View 4G|PG41200|PG09410', 'MotorolaTablet' => 'xoom|sholest|MZ615|MZ605|MZ505|MZ601|MZ602|MZ603|MZ604|MZ606|MZ607|MZ608|MZ609|MZ615|MZ616|MZ617', 'NookTablet' => 'Android.*Nook|NookColor|nook browser|BNRV200|BNRV200A|BNTV250|BNTV250A|BNTV400|BNTV600|LogicPD Zoom2', // http://www.acer.ro/ac/ro/RO/content/drivers // http://www.packardbell.co.uk/pb/en/GB/content/download (Packard Bell is part of Acer) // http://us.acer.com/ac/en/US/content/group/tablets // http://www.acer.de/ac/de/DE/content/models/tablets/ // Can conflict with Micromax and Motorola phones codes. 'AcerTablet' => 'Android.*; \b(A100|A101|A110|A200|A210|A211|A500|A501|A510|A511|A700|A701|W500|W500P|W501|W501P|W510|W511|W700|G100|G100W|B1-A71|B1-710|B1-711|A1-810|A1-811|A1-830)\b|W3-810|\bA3-A10\b|\bA3-A11\b|\bA3-A20\b|\bA3-A30', // http://eu.computers.toshiba-europe.com/innovation/family/Tablets/1098744/banner_id/tablet_footerlink/ // http://us.toshiba.com/tablets/tablet-finder // http://www.toshiba.co.jp/regza/tablet/ 'ToshibaTablet' => 'Android.*(AT100|AT105|AT200|AT205|AT270|AT275|AT300|AT305|AT1S5|AT500|AT570|AT700|AT830)|TOSHIBA.*FOLIO', // http://www.nttdocomo.co.jp/english/service/developer/smart_phone/technical_info/spec/index.html // http://www.lg.com/us/tablets 'LGTablet' => '\bL-06C|LG-V909|LG-V900|LG-V700|LG-V510|LG-V500|LG-V410|LG-V400|LG-VK810\b', 'FujitsuTablet' => 'Android.*\b(F-01D|F-02F|F-05E|F-10D|M532|Q572)\b', // Prestigio Tablets http://www.prestigio.com/support 'PrestigioTablet' => 'PMP3170B|PMP3270B|PMP3470B|PMP7170B|PMP3370B|PMP3570C|PMP5870C|PMP3670B|PMP5570C|PMP5770D|PMP3970B|PMP3870C|PMP5580C|PMP5880D|PMP5780D|PMP5588C|PMP7280C|PMP7280C3G|PMP7280|PMP7880D|PMP5597D|PMP5597|PMP7100D|PER3464|PER3274|PER3574|PER3884|PER5274|PER5474|PMP5097CPRO|PMP5097|PMP7380D|PMP5297C|PMP5297C_QUAD|PMP812E|PMP812E3G|PMP812F|PMP810E|PMP880TD|PMT3017|PMT3037|PMT3047|PMT3057|PMT7008|PMT5887|PMT5001|PMT5002', // http://support.lenovo.com/en_GB/downloads/default.page?# 'LenovoTablet' => 'Lenovo TAB|Idea(Tab|Pad)( A1|A10| K1|)|ThinkPad([ ]+)?Tablet|YT3-850M|YT3-X90L|YT3-X90F|YT3-X90X|Lenovo.*(S2109|S2110|S5000|S6000|K3011|A3000|A3500|A1000|A2107|A2109|A1107|A5500|A7600|B6000|B8000|B8080)(-|)(FL|F|HV|H|)|TB-X103F|TB-X304F|TB-8703F', // http://www.dell.com/support/home/us/en/04/Products/tab_mob/tablets 'DellTablet' => 'Venue 11|Venue 8|Venue 7|Dell Streak 10|Dell Streak 7', // http://www.yarvik.com/en/matrix/tablets/ 'YarvikTablet' => 'Android.*\b(TAB210|TAB211|TAB224|TAB250|TAB260|TAB264|TAB310|TAB360|TAB364|TAB410|TAB411|TAB420|TAB424|TAB450|TAB460|TAB461|TAB464|TAB465|TAB467|TAB468|TAB07-100|TAB07-101|TAB07-150|TAB07-151|TAB07-152|TAB07-200|TAB07-201-3G|TAB07-210|TAB07-211|TAB07-212|TAB07-214|TAB07-220|TAB07-400|TAB07-485|TAB08-150|TAB08-200|TAB08-201-3G|TAB08-201-30|TAB09-100|TAB09-211|TAB09-410|TAB10-150|TAB10-201|TAB10-211|TAB10-400|TAB10-410|TAB13-201|TAB274EUK|TAB275EUK|TAB374EUK|TAB462EUK|TAB474EUK|TAB9-200)\b', 'MedionTablet' => 'Android.*\bOYO\b|LIFE.*(P9212|P9514|P9516|S9512)|LIFETAB', 'ArnovaTablet' => '97G4|AN10G2|AN7bG3|AN7fG3|AN8G3|AN8cG3|AN7G3|AN9G3|AN7dG3|AN7dG3ST|AN7dG3ChildPad|AN10bG3|AN10bG3DT|AN9G2', // http://www.intenso.de/kategorie_en.php?kategorie=33 // @todo: http://www.nbhkdz.com/read/b8e64202f92a2df129126bff.html - investigate 'IntensoTablet' => 'INM8002KP|INM1010FP|INM805ND|Intenso Tab|TAB1004', // IRU.ru Tablets http://www.iru.ru/catalog/soho/planetable/ 'IRUTablet' => 'M702pro', 'MegafonTablet' => 'MegaFon V9|\bZTE V9\b|Android.*\bMT7A\b', // http://www.e-boda.ro/tablete-pc.html 'EbodaTablet' => 'E-Boda (Supreme|Impresspeed|Izzycomm|Essential)', // http://www.allview.ro/produse/droseries/lista-tablete-pc/ 'AllViewTablet' => 'Allview.*(Viva|Alldro|City|Speed|All TV|Frenzy|Quasar|Shine|TX1|AX1|AX2)', // http://wiki.archosfans.com/index.php?title=Main_Page // @note Rewrite the regex format after we add more UAs. 'ArchosTablet' => '\b(101G9|80G9|A101IT)\b|Qilive 97R|Archos5|\bARCHOS (70|79|80|90|97|101|FAMILYPAD|)(b|c|)(G10| Cobalt| TITANIUM(HD|)| Xenon| Neon|XSK| 2| XS 2| PLATINUM| CARBON|GAMEPAD)\b', // http://www.ainol.com/plugin.php?identifier=ainol&module=product 'AinolTablet' => 'NOVO7|NOVO8|NOVO10|Novo7Aurora|Novo7Basic|NOVO7PALADIN|novo9-Spark', 'NokiaLumiaTablet' => 'Lumia 2520', // @todo: inspect http://esupport.sony.com/US/p/select-system.pl?DIRECTOR=DRIVER // Readers http://www.atsuhiro-me.net/ebook/sony-reader/sony-reader-web-browser // http://www.sony.jp/support/tablet/ 'SonyTablet' => 'Sony.*Tablet|Xperia Tablet|Sony Tablet S|SO-03E|SGPT12|SGPT13|SGPT114|SGPT121|SGPT122|SGPT123|SGPT111|SGPT112|SGPT113|SGPT131|SGPT132|SGPT133|SGPT211|SGPT212|SGPT213|SGP311|SGP312|SGP321|EBRD1101|EBRD1102|EBRD1201|SGP351|SGP341|SGP511|SGP512|SGP521|SGP541|SGP551|SGP621|SGP612|SOT31', // http://www.support.philips.com/support/catalog/worldproducts.jsp?userLanguage=en&userCountry=cn&categoryid=3G_LTE_TABLET_SU_CN_CARE&title=3G%20tablets%20/%20LTE%20range&_dyncharset=UTF-8 'PhilipsTablet' => '\b(PI2010|PI3000|PI3100|PI3105|PI3110|PI3205|PI3210|PI3900|PI4010|PI7000|PI7100)\b', // db + http://www.cube-tablet.com/buy-products.html 'CubeTablet' => 'Android.*(K8GT|U9GT|U10GT|U16GT|U17GT|U18GT|U19GT|U20GT|U23GT|U30GT)|CUBE U8GT', // http://www.cobyusa.com/?p=pcat&pcat_id=3001 'CobyTablet' => 'MID1042|MID1045|MID1125|MID1126|MID7012|MID7014|MID7015|MID7034|MID7035|MID7036|MID7042|MID7048|MID7127|MID8042|MID8048|MID8127|MID9042|MID9740|MID9742|MID7022|MID7010', // http://www.match.net.cn/products.asp 'MIDTablet' => 'M9701|M9000|M9100|M806|M1052|M806|T703|MID701|MID713|MID710|MID727|MID760|MID830|MID728|MID933|MID125|MID810|MID732|MID120|MID930|MID800|MID731|MID900|MID100|MID820|MID735|MID980|MID130|MID833|MID737|MID960|MID135|MID860|MID736|MID140|MID930|MID835|MID733|MID4X10', // http://www.msi.com/support // @todo Research the Windows Tablets. 'MSITablet' => 'MSI \b(Primo 73K|Primo 73L|Primo 81L|Primo 77|Primo 93|Primo 75|Primo 76|Primo 73|Primo 81|Primo 91|Primo 90|Enjoy 71|Enjoy 7|Enjoy 10)\b', // @todo http://www.kyoceramobile.com/support/drivers/ // 'KyoceraTablet' => null, // @todo http://intexuae.com/index.php/category/mobile-devices/tablets-products/ // 'IntextTablet' => null, // http://pdadb.net/index.php?m=pdalist&list=SMiT (NoName Chinese Tablets) // http://www.imp3.net/14/show.php?itemid=20454 'SMiTTablet' => 'Android.*(\bMID\b|MID-560|MTV-T1200|MTV-PND531|MTV-P1101|MTV-PND530)', // http://www.rock-chips.com/index.php?do=prod&pid=2 'RockChipTablet' => 'Android.*(RK2818|RK2808A|RK2918|RK3066)|RK2738|RK2808A', // http://www.fly-phone.com/devices/tablets/ ; http://www.fly-phone.com/service/ 'FlyTablet' => 'IQ310|Fly Vision', // http://www.bqreaders.com/gb/tablets-prices-sale.html 'bqTablet' => 'Android.*(bq)?.*(Elcano|Curie|Edison|Maxwell|Kepler|Pascal|Tesla|Hypatia|Platon|Newton|Livingstone|Cervantes|Avant|Aquaris ([E|M]10|M8))|Maxwell.*Lite|Maxwell.*Plus', // http://www.huaweidevice.com/worldwide/productFamily.do?method=index&directoryId=5011&treeId=3290 // http://www.huaweidevice.com/worldwide/downloadCenter.do?method=index&directoryId=3372&treeId=0&tb=1&type=software (including legacy tablets) 'HuaweiTablet' => 'MediaPad|MediaPad 7 Youth|IDEOS S7|S7-201c|S7-202u|S7-101|S7-103|S7-104|S7-105|S7-106|S7-201|S7-Slim|M2-A01L', // Nec or Medias Tab 'NecTablet' => '\bN-06D|\bN-08D', // Pantech Tablets: http://www.pantechusa.com/phones/ 'PantechTablet' => 'Pantech.*P4100', // Broncho Tablets: http://www.broncho.cn/ (hard to find) 'BronchoTablet' => 'Broncho.*(N701|N708|N802|a710)', // http://versusuk.com/support.html 'VersusTablet' => 'TOUCHPAD.*[78910]|\bTOUCHTAB\b', // http://www.zync.in/index.php/our-products/tablet-phablets 'ZyncTablet' => 'z1000|Z99 2G|z99|z930|z999|z990|z909|Z919|z900', // http://www.positivoinformatica.com.br/www/pessoal/tablet-ypy/ 'PositivoTablet' => 'TB07STA|TB10STA|TB07FTA|TB10FTA', // https://www.nabitablet.com/ 'NabiTablet' => 'Android.*\bNabi', 'KoboTablet' => 'Kobo Touch|\bK080\b|\bVox\b Build|\bArc\b Build', // French Danew Tablets http://www.danew.com/produits-tablette.php 'DanewTablet' => 'DSlide.*\b(700|701R|702|703R|704|802|970|971|972|973|974|1010|1012)\b', // Texet Tablets and Readers http://www.texet.ru/tablet/ 'TexetTablet' => 'NaviPad|TB-772A|TM-7045|TM-7055|TM-9750|TM-7016|TM-7024|TM-7026|TM-7041|TM-7043|TM-7047|TM-8041|TM-9741|TM-9747|TM-9748|TM-9751|TM-7022|TM-7021|TM-7020|TM-7011|TM-7010|TM-7023|TM-7025|TM-7037W|TM-7038W|TM-7027W|TM-9720|TM-9725|TM-9737W|TM-1020|TM-9738W|TM-9740|TM-9743W|TB-807A|TB-771A|TB-727A|TB-725A|TB-719A|TB-823A|TB-805A|TB-723A|TB-715A|TB-707A|TB-705A|TB-709A|TB-711A|TB-890HD|TB-880HD|TB-790HD|TB-780HD|TB-770HD|TB-721HD|TB-710HD|TB-434HD|TB-860HD|TB-840HD|TB-760HD|TB-750HD|TB-740HD|TB-730HD|TB-722HD|TB-720HD|TB-700HD|TB-500HD|TB-470HD|TB-431HD|TB-430HD|TB-506|TB-504|TB-446|TB-436|TB-416|TB-146SE|TB-126SE', // Avoid detecting 'PLAYSTATION 3' as mobile. 'PlaystationTablet' => 'Playstation.*(Portable|Vita)', // http://www.trekstor.de/surftabs.html 'TrekstorTablet' => 'ST10416-1|VT10416-1|ST70408-1|ST702xx-1|ST702xx-2|ST80208|ST97216|ST70104-2|VT10416-2|ST10216-2A|SurfTab', // http://www.pyleaudio.com/Products.aspx?%2fproducts%2fPersonal-Electronics%2fTablets 'PyleAudioTablet' => '\b(PTBL10CEU|PTBL10C|PTBL72BC|PTBL72BCEU|PTBL7CEU|PTBL7C|PTBL92BC|PTBL92BCEU|PTBL9CEU|PTBL9CUK|PTBL9C)\b', // http://www.advandigital.com/index.php?link=content-product&jns=JP001 // because of the short codenames we have to include whitespaces to reduce the possible conflicts. 'AdvanTablet' => 'Android.* \b(E3A|T3X|T5C|T5B|T3E|T3C|T3B|T1J|T1F|T2A|T1H|T1i|E1C|T1-E|T5-A|T4|E1-B|T2Ci|T1-B|T1-D|O1-A|E1-A|T1-A|T3A|T4i)\b ', // http://www.danytech.com/category/tablet-pc 'DanyTechTablet' => 'Genius Tab G3|Genius Tab S2|Genius Tab Q3|Genius Tab G4|Genius Tab Q4|Genius Tab G-II|Genius TAB GII|Genius TAB GIII|Genius Tab S1', // http://www.galapad.net/product.html 'GalapadTablet' => 'Android.*\bG1\b', // http://www.micromaxinfo.com/tablet/funbook 'MicromaxTablet' => 'Funbook|Micromax.*\b(P250|P560|P360|P362|P600|P300|P350|P500|P275)\b', // http://www.karbonnmobiles.com/products_tablet.php 'KarbonnTablet' => 'Android.*\b(A39|A37|A34|ST8|ST10|ST7|Smart Tab3|Smart Tab2)\b', // http://www.myallfine.com/Products.asp 'AllFineTablet' => 'Fine7 Genius|Fine7 Shine|Fine7 Air|Fine8 Style|Fine9 More|Fine10 Joy|Fine11 Wide', // http://www.proscanvideo.com/products-search.asp?itemClass=TABLET&itemnmbr= 'PROSCANTablet' => '\b(PEM63|PLT1023G|PLT1041|PLT1044|PLT1044G|PLT1091|PLT4311|PLT4311PL|PLT4315|PLT7030|PLT7033|PLT7033D|PLT7035|PLT7035D|PLT7044K|PLT7045K|PLT7045KB|PLT7071KG|PLT7072|PLT7223G|PLT7225G|PLT7777G|PLT7810K|PLT7849G|PLT7851G|PLT7852G|PLT8015|PLT8031|PLT8034|PLT8036|PLT8080K|PLT8082|PLT8088|PLT8223G|PLT8234G|PLT8235G|PLT8816K|PLT9011|PLT9045K|PLT9233G|PLT9735|PLT9760G|PLT9770G)\b', // http://www.yonesnav.com/products/products.php 'YONESTablet' => 'BQ1078|BC1003|BC1077|RK9702|BC9730|BC9001|IT9001|BC7008|BC7010|BC708|BC728|BC7012|BC7030|BC7027|BC7026', // http://www.cjshowroom.com/eproducts.aspx?classcode=004001001 // China manufacturer makes tablets for different small brands (eg. http://www.zeepad.net/index.html) 'ChangJiaTablet' => 'TPC7102|TPC7103|TPC7105|TPC7106|TPC7107|TPC7201|TPC7203|TPC7205|TPC7210|TPC7708|TPC7709|TPC7712|TPC7110|TPC8101|TPC8103|TPC8105|TPC8106|TPC8203|TPC8205|TPC8503|TPC9106|TPC9701|TPC97101|TPC97103|TPC97105|TPC97106|TPC97111|TPC97113|TPC97203|TPC97603|TPC97809|TPC97205|TPC10101|TPC10103|TPC10106|TPC10111|TPC10203|TPC10205|TPC10503', // http://www.gloryunion.cn/products.asp // http://www.allwinnertech.com/en/apply/mobile.html // http://www.ptcl.com.pk/pd_content.php?pd_id=284 (EVOTAB) // @todo: Softwiner tablets? // aka. Cute or Cool tablets. Not sure yet, must research to avoid collisions. 'GUTablet' => 'TX-A1301|TX-M9002|Q702|kf026', // A12R|D75A|D77|D79|R83|A95|A106C|R15|A75|A76|D71|D72|R71|R73|R77|D82|R85|D92|A97|D92|R91|A10F|A77F|W71F|A78F|W78F|W81F|A97F|W91F|W97F|R16G|C72|C73E|K72|K73|R96G // http://www.pointofview-online.com/showroom.php?shop_mode=product_listing&category_id=118 'PointOfViewTablet' => 'TAB-P506|TAB-navi-7-3G-M|TAB-P517|TAB-P-527|TAB-P701|TAB-P703|TAB-P721|TAB-P731N|TAB-P741|TAB-P825|TAB-P905|TAB-P925|TAB-PR945|TAB-PL1015|TAB-P1025|TAB-PI1045|TAB-P1325|TAB-PROTAB[0-9]+|TAB-PROTAB25|TAB-PROTAB26|TAB-PROTAB27|TAB-PROTAB26XL|TAB-PROTAB2-IPS9|TAB-PROTAB30-IPS9|TAB-PROTAB25XXL|TAB-PROTAB26-IPS10|TAB-PROTAB30-IPS10', // http://www.overmax.pl/pl/katalog-produktow,p8/tablety,c14/ // @todo: add more tests. 'OvermaxTablet' => 'OV-(SteelCore|NewBase|Basecore|Baseone|Exellen|Quattor|EduTab|Solution|ACTION|BasicTab|TeddyTab|MagicTab|Stream|TB-08|TB-09)|Qualcore 1027', // http://hclmetablet.com/India/index.php 'HCLTablet' => 'HCL.*Tablet|Connect-3G-2.0|Connect-2G-2.0|ME Tablet U1|ME Tablet U2|ME Tablet G1|ME Tablet X1|ME Tablet Y2|ME Tablet Sync', // http://www.edigital.hu/Tablet_es_e-book_olvaso/Tablet-c18385.html 'DPSTablet' => 'DPS Dream 9|DPS Dual 7', // http://www.visture.com/index.asp 'VistureTablet' => 'V97 HD|i75 3G|Visture V4( HD)?|Visture V5( HD)?|Visture V10', // http://www.mijncresta.nl/tablet 'CrestaTablet' => 'CTP(-)?810|CTP(-)?818|CTP(-)?828|CTP(-)?838|CTP(-)?888|CTP(-)?978|CTP(-)?980|CTP(-)?987|CTP(-)?988|CTP(-)?989', // MediaTek - http://www.mediatek.com/_en/01_products/02_proSys.php?cata_sn=1&cata1_sn=1&cata2_sn=309 'MediatekTablet' => '\bMT8125|MT8389|MT8135|MT8377\b', // Concorde tab 'ConcordeTablet' => 'Concorde([ ]+)?Tab|ConCorde ReadMan', // GoClever Tablets - http://www.goclever.com/uk/products,c1/tablet,c5/ 'GoCleverTablet' => 'GOCLEVER TAB|A7GOCLEVER|M1042|M7841|M742|R1042BK|R1041|TAB A975|TAB A7842|TAB A741|TAB A741L|TAB M723G|TAB M721|TAB A1021|TAB I921|TAB R721|TAB I720|TAB T76|TAB R70|TAB R76.2|TAB R106|TAB R83.2|TAB M813G|TAB I721|GCTA722|TAB I70|TAB I71|TAB S73|TAB R73|TAB R74|TAB R93|TAB R75|TAB R76.1|TAB A73|TAB A93|TAB A93.2|TAB T72|TAB R83|TAB R974|TAB R973|TAB A101|TAB A103|TAB A104|TAB A104.2|R105BK|M713G|A972BK|TAB A971|TAB R974.2|TAB R104|TAB R83.3|TAB A1042', // Modecom Tablets - http://www.modecom.eu/tablets/portal/ 'ModecomTablet' => 'FreeTAB 9000|FreeTAB 7.4|FreeTAB 7004|FreeTAB 7800|FreeTAB 2096|FreeTAB 7.5|FreeTAB 1014|FreeTAB 1001 |FreeTAB 8001|FreeTAB 9706|FreeTAB 9702|FreeTAB 7003|FreeTAB 7002|FreeTAB 1002|FreeTAB 7801|FreeTAB 1331|FreeTAB 1004|FreeTAB 8002|FreeTAB 8014|FreeTAB 9704|FreeTAB 1003', // Vonino Tablets - http://www.vonino.eu/tablets 'VoninoTablet' => '\b(Argus[ _]?S|Diamond[ _]?79HD|Emerald[ _]?78E|Luna[ _]?70C|Onyx[ _]?S|Onyx[ _]?Z|Orin[ _]?HD|Orin[ _]?S|Otis[ _]?S|SpeedStar[ _]?S|Magnet[ _]?M9|Primus[ _]?94[ _]?3G|Primus[ _]?94HD|Primus[ _]?QS|Android.*\bQ8\b|Sirius[ _]?EVO[ _]?QS|Sirius[ _]?QS|Spirit[ _]?S)\b', // ECS Tablets - http://www.ecs.com.tw/ECSWebSite/Product/Product_Tablet_List.aspx?CategoryID=14&MenuID=107&childid=M_107&LanID=0 'ECSTablet' => 'V07OT2|TM105A|S10OT1|TR10CS1', // Storex Tablets - http://storex.fr/espace_client/support.html // @note: no need to add all the tablet codes since they are guided by the first regex. 'StorexTablet' => 'eZee[_\']?(Tab|Go)[0-9]+|TabLC7|Looney Tunes Tab', // Generic Vodafone tablets. 'VodafoneTablet' => 'SmartTab([ ]+)?[0-9]+|SmartTabII10|SmartTabII7|VF-1497', // French tablets - Essentiel B http://www.boulanger.fr/tablette_tactile_e-book/tablette_tactile_essentiel_b/cl_68908.htm?multiChoiceToDelete=brand&mc_brand=essentielb // Aka: http://www.essentielb.fr/ 'EssentielBTablet' => 'Smart[ \']?TAB[ ]+?[0-9]+|Family[ \']?TAB2', // Ross & Moor - http://ross-moor.ru/ 'RossMoorTablet' => 'RM-790|RM-997|RMD-878G|RMD-974R|RMT-705A|RMT-701|RME-601|RMT-501|RMT-711', // i-mobile http://product.i-mobilephone.com/Mobile_Device 'iMobileTablet' => 'i-mobile i-note', // http://www.tolino.de/de/vergleichen/ 'TolinoTablet' => 'tolino tab [0-9.]+|tolino shine', // AudioSonic - a Kmart brand // http://www.kmart.com.au/webapp/wcs/stores/servlet/Search?langId=-1&storeId=10701&catalogId=10001&categoryId=193001&pageSize=72¤tPage=1&searchCategory=193001%2b4294965664&sortBy=p_MaxPrice%7c1 'AudioSonicTablet' => '\bC-22Q|T7-QC|T-17B|T-17P\b', // AMPE Tablets - http://www.ampe.com.my/product-category/tablets/ // @todo: add them gradually to avoid conflicts. 'AMPETablet' => 'Android.* A78 ', // Skk Mobile - http://skkmobile.com.ph/product_tablets.php 'SkkTablet' => 'Android.* (SKYPAD|PHOENIX|CYCLOPS)', // Tecno Mobile (only tablet) - http://www.tecno-mobile.com/index.php/product?filterby=smart&list_order=all&page=1 'TecnoTablet' => 'TECNO P9', // JXD (consoles & tablets) - http://jxd.hk/products.asp?selectclassid=009008&clsid=3 'JXDTablet' => 'Android.* \b(F3000|A3300|JXD5000|JXD3000|JXD2000|JXD300B|JXD300|S5800|S7800|S602b|S5110b|S7300|S5300|S602|S603|S5100|S5110|S601|S7100a|P3000F|P3000s|P101|P200s|P1000m|P200m|P9100|P1000s|S6600b|S908|P1000|P300|S18|S6600|S9100)\b', // i-Joy tablets - http://www.i-joy.es/en/cat/products/tablets/ 'iJoyTablet' => 'Tablet (Spirit 7|Essentia|Galatea|Fusion|Onix 7|Landa|Titan|Scooby|Deox|Stella|Themis|Argon|Unique 7|Sygnus|Hexen|Finity 7|Cream|Cream X2|Jade|Neon 7|Neron 7|Kandy|Scape|Saphyr 7|Rebel|Biox|Rebel|Rebel 8GB|Myst|Draco 7|Myst|Tab7-004|Myst|Tadeo Jones|Tablet Boing|Arrow|Draco Dual Cam|Aurix|Mint|Amity|Revolution|Finity 9|Neon 9|T9w|Amity 4GB Dual Cam|Stone 4GB|Stone 8GB|Andromeda|Silken|X2|Andromeda II|Halley|Flame|Saphyr 9,7|Touch 8|Planet|Triton|Unique 10|Hexen 10|Memphis 4GB|Memphis 8GB|Onix 10)', // http://www.intracon.eu/tablet 'FX2Tablet' => 'FX2 PAD7|FX2 PAD10', // http://www.xoro.de/produkte/ // @note: Might be the same brand with 'Simply tablets' 'XoroTablet' => 'KidsPAD 701|PAD[ ]?712|PAD[ ]?714|PAD[ ]?716|PAD[ ]?717|PAD[ ]?718|PAD[ ]?720|PAD[ ]?721|PAD[ ]?722|PAD[ ]?790|PAD[ ]?792|PAD[ ]?900|PAD[ ]?9715D|PAD[ ]?9716DR|PAD[ ]?9718DR|PAD[ ]?9719QR|PAD[ ]?9720QR|TelePAD1030|Telepad1032|TelePAD730|TelePAD731|TelePAD732|TelePAD735Q|TelePAD830|TelePAD9730|TelePAD795|MegaPAD 1331|MegaPAD 1851|MegaPAD 2151', // http://www1.viewsonic.com/products/computing/tablets/ 'ViewsonicTablet' => 'ViewPad 10pi|ViewPad 10e|ViewPad 10s|ViewPad E72|ViewPad7|ViewPad E100|ViewPad 7e|ViewSonic VB733|VB100a', // https://www.verizonwireless.com/tablets/verizon/ 'VerizonTablet' => 'QTAQZ3|QTAIR7|QTAQTZ3|QTASUN1|QTASUN2|QTAXIA1', // http://www.odys.de/web/internet-tablet_en.html 'OdysTablet' => 'LOOX|XENO10|ODYS[ -](Space|EVO|Xpress|NOON)|\bXELIO\b|Xelio10Pro|XELIO7PHONETAB|XELIO10EXTREME|XELIOPT2|NEO_QUAD10', // http://www.captiva-power.de/products.html#tablets-en 'CaptivaTablet' => 'CAPTIVA PAD', // IconBIT - http://www.iconbit.com/products/tablets/ 'IconbitTablet' => 'NetTAB|NT-3702|NT-3702S|NT-3702S|NT-3603P|NT-3603P|NT-0704S|NT-0704S|NT-3805C|NT-3805C|NT-0806C|NT-0806C|NT-0909T|NT-0909T|NT-0907S|NT-0907S|NT-0902S|NT-0902S', // http://www.teclast.com/topic.php?channelID=70&topicID=140&pid=63 'TeclastTablet' => 'T98 4G|\bP80\b|\bX90HD\b|X98 Air|X98 Air 3G|\bX89\b|P80 3G|\bX80h\b|P98 Air|\bX89HD\b|P98 3G|\bP90HD\b|P89 3G|X98 3G|\bP70h\b|P79HD 3G|G18d 3G|\bP79HD\b|\bP89s\b|\bA88\b|\bP10HD\b|\bP19HD\b|G18 3G|\bP78HD\b|\bA78\b|\bP75\b|G17s 3G|G17h 3G|\bP85t\b|\bP90\b|\bP11\b|\bP98t\b|\bP98HD\b|\bG18d\b|\bP85s\b|\bP11HD\b|\bP88s\b|\bA80HD\b|\bA80se\b|\bA10h\b|\bP89\b|\bP78s\b|\bG18\b|\bP85\b|\bA70h\b|\bA70\b|\bG17\b|\bP18\b|\bA80s\b|\bA11s\b|\bP88HD\b|\bA80h\b|\bP76s\b|\bP76h\b|\bP98\b|\bA10HD\b|\bP78\b|\bP88\b|\bA11\b|\bA10t\b|\bP76a\b|\bP76t\b|\bP76e\b|\bP85HD\b|\bP85a\b|\bP86\b|\bP75HD\b|\bP76v\b|\bA12\b|\bP75a\b|\bA15\b|\bP76Ti\b|\bP81HD\b|\bA10\b|\bT760VE\b|\bT720HD\b|\bP76\b|\bP73\b|\bP71\b|\bP72\b|\bT720SE\b|\bC520Ti\b|\bT760\b|\bT720VE\b|T720-3GE|T720-WiFi', // Onda - http://www.onda-tablet.com/buy-android-onda.html?dir=desc&limit=all&order=price 'OndaTablet' => '\b(V975i|Vi30|VX530|V701|Vi60|V701s|Vi50|V801s|V719|Vx610w|VX610W|V819i|Vi10|VX580W|Vi10|V711s|V813|V811|V820w|V820|Vi20|V711|VI30W|V712|V891w|V972|V819w|V820w|Vi60|V820w|V711|V813s|V801|V819|V975s|V801|V819|V819|V818|V811|V712|V975m|V101w|V961w|V812|V818|V971|V971s|V919|V989|V116w|V102w|V973|Vi40)\b[\s]+', 'JaytechTablet' => 'TPC-PA762', 'BlaupunktTablet' => 'Endeavour 800NG|Endeavour 1010', // http://www.digma.ru/support/download/ // @todo: Ebooks also (if requested) 'DigmaTablet' => '\b(iDx10|iDx9|iDx8|iDx7|iDxD7|iDxD8|iDsQ8|iDsQ7|iDsQ8|iDsD10|iDnD7|3TS804H|iDsQ11|iDj7|iDs10)\b', // http://www.evolioshop.com/ro/tablete-pc.html // http://www.evolio.ro/support/downloads_static.html?cat=2 // @todo: Research some more 'EvolioTablet' => 'ARIA_Mini_wifi|Aria[ _]Mini|Evolio X10|Evolio X7|Evolio X8|\bEvotab\b|\bNeura\b', // @todo http://www.lavamobiles.com/tablets-data-cards 'LavaTablet' => 'QPAD E704|\bIvoryS\b|E-TAB IVORY|\bE-TAB\b', // http://www.breezetablet.com/ 'AocTablet' => 'MW0811|MW0812|MW0922|MTK8382|MW1031|MW0831|MW0821|MW0931|MW0712', // http://www.mpmaneurope.com/en/products/internet-tablets-14/android-tablets-14/ 'MpmanTablet' => 'MP11 OCTA|MP10 OCTA|MPQC1114|MPQC1004|MPQC994|MPQC974|MPQC973|MPQC804|MPQC784|MPQC780|\bMPG7\b|MPDCG75|MPDCG71|MPDC1006|MP101DC|MPDC9000|MPDC905|MPDC706HD|MPDC706|MPDC705|MPDC110|MPDC100|MPDC99|MPDC97|MPDC88|MPDC8|MPDC77|MP709|MID701|MID711|MID170|MPDC703|MPQC1010', // https://www.celkonmobiles.com/?_a=categoryphones&sid=2 'CelkonTablet' => 'CT695|CT888|CT[\s]?910|CT7 Tab|CT9 Tab|CT3 Tab|CT2 Tab|CT1 Tab|C820|C720|\bCT-1\b', // http://www.wolderelectronics.com/productos/manuales-y-guias-rapidas/categoria-2-miTab 'WolderTablet' => 'miTab \b(DIAMOND|SPACE|BROOKLYN|NEO|FLY|MANHATTAN|FUNK|EVOLUTION|SKY|GOCAR|IRON|GENIUS|POP|MINT|EPSILON|BROADWAY|JUMP|HOP|LEGEND|NEW AGE|LINE|ADVANCE|FEEL|FOLLOW|LIKE|LINK|LIVE|THINK|FREEDOM|CHICAGO|CLEVELAND|BALTIMORE-GH|IOWA|BOSTON|SEATTLE|PHOENIX|DALLAS|IN 101|MasterChef)\b', // http://www.mi.com/en 'MiTablet' => '\bMI PAD\b|\bHM NOTE 1W\b', // http://www.nbru.cn/index.html 'NibiruTablet' => 'Nibiru M1|Nibiru Jupiter One', // http://navroad.com/products/produkty/tablety/ // http://navroad.com/products/produkty/tablety/ 'NexoTablet' => 'NEXO NOVA|NEXO 10|NEXO AVIO|NEXO FREE|NEXO GO|NEXO EVO|NEXO 3G|NEXO SMART|NEXO KIDDO|NEXO MOBI', // http://leader-online.com/new_site/product-category/tablets/ // http://www.leader-online.net.au/List/Tablet 'LeaderTablet' => 'TBLT10Q|TBLT10I|TBL-10WDKB|TBL-10WDKBO2013|TBL-W230V2|TBL-W450|TBL-W500|SV572|TBLT7I|TBA-AC7-8G|TBLT79|TBL-8W16|TBL-10W32|TBL-10WKB|TBL-W100', // http://www.datawind.com/ubislate/ 'UbislateTablet' => 'UbiSlate[\s]?7C', // http://www.pocketbook-int.com/ru/support 'PocketBookTablet' => 'Pocketbook', // http://www.kocaso.com/product_tablet.html 'KocasoTablet' => '\b(TB-1207)\b', // http://global.hisense.com/product/asia/tablet/Sero7/201412/t20141215_91832.htm 'HisenseTablet' => '\b(F5281|E2371)\b', // http://www.tesco.com/direct/hudl/ 'Hudl' => 'Hudl HT7S3|Hudl 2', // http://www.telstra.com.au/home-phone/thub-2/ 'TelstraTablet' => 'T-Hub2', 'GenericTablet' => 'Android.*\b97D\b|Tablet(?!.*PC)|BNTV250A|MID-WCDMA|LogicPD Zoom2|\bA7EB\b|CatNova8|A1_07|CT704|CT1002|\bM721\b|rk30sdk|\bEVOTAB\b|M758A|ET904|ALUMIUM10|Smartfren Tab|Endeavour 1010|Tablet-PC-4|Tagi Tab|\bM6pro\b|CT1020W|arc 10HD|\bTP750\b|\bQTAQZ3\b' ); /** * List of mobile Operating Systems. * * @var array */ protected static $operatingSystems = array( 'AndroidOS' => 'Android', 'BlackBerryOS' => 'blackberry|\bBB10\b|rim tablet os', 'PalmOS' => 'PalmOS|avantgo|blazer|elaine|hiptop|palm|plucker|xiino', 'SymbianOS' => 'Symbian|SymbOS|Series60|Series40|SYB-[0-9]+|\bS60\b', // @reference: http://en.wikipedia.org/wiki/Windows_Mobile 'WindowsMobileOS' => 'Windows CE.*(PPC|Smartphone|Mobile|[0-9]{3}x[0-9]{3})|Window Mobile|Windows Phone [0-9.]+|WCE;', // @reference: http://en.wikipedia.org/wiki/Windows_Phone // http://wifeng.cn/?r=blog&a=view&id=106 // http://nicksnettravels.builttoroam.com/post/2011/01/10/Bogus-Windows-Phone-7-User-Agent-String.aspx // http://msdn.microsoft.com/library/ms537503.aspx // https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx 'WindowsPhoneOS' => 'Windows Phone 10.0|Windows Phone 8.1|Windows Phone 8.0|Windows Phone OS|XBLWP7|ZuneWP7|Windows NT 6.[23]; ARM;', 'iOS' => '\biPhone.*Mobile|\biPod|\biPad|AppleCoreMedia', // http://en.wikipedia.org/wiki/MeeGo // @todo: research MeeGo in UAs 'MeeGoOS' => 'MeeGo', // http://en.wikipedia.org/wiki/Maemo // @todo: research Maemo in UAs 'MaemoOS' => 'Maemo', 'JavaOS' => 'J2ME/|\bMIDP\b|\bCLDC\b', // '|Java/' produces bug #135 'webOS' => 'webOS|hpwOS', 'badaOS' => '\bBada\b', 'BREWOS' => 'BREW', ); /** * List of mobile User Agents. * * IMPORTANT: This is a list of only mobile browsers. * Mobile Detect 2.x supports only mobile browsers, * it was never designed to detect all browsers. * The change will come in 2017 in the 3.x release for PHP7. * * @var array */ protected static $browsers = array( //'Vivaldi' => 'Vivaldi', // @reference: https://developers.google.com/chrome/mobile/docs/user-agent 'Chrome' => '\bCrMo\b|CriOS|Android.*Chrome/[.0-9]* (Mobile)?', 'Dolfin' => '\bDolfin\b', 'Opera' => 'Opera.*Mini|Opera.*Mobi|Android.*Opera|Mobile.*OPR/[0-9.]+|Coast/[0-9.]+', 'Skyfire' => 'Skyfire', 'Edge' => 'Mobile Safari/[.0-9]* Edge', 'IE' => 'IEMobile|MSIEMobile', // |Trident/[.0-9]+ 'Firefox' => 'fennec|firefox.*maemo|(Mobile|Tablet).*Firefox|Firefox.*Mobile|FxiOS', 'Bolt' => 'bolt', 'TeaShark' => 'teashark', 'Blazer' => 'Blazer', // @reference: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/OptimizingforSafarioniPhone/OptimizingforSafarioniPhone.html#//apple_ref/doc/uid/TP40006517-SW3 'Safari' => 'Version.*Mobile.*Safari|Safari.*Mobile|MobileSafari', // http://en.wikipedia.org/wiki/Midori_(web_browser) //'Midori' => 'midori', //'Tizen' => 'Tizen', 'UCBrowser' => 'UC.*Browser|UCWEB', 'baiduboxapp' => 'baiduboxapp', 'baidubrowser' => 'baidubrowser', // https://github.com/serbanghita/Mobile-Detect/issues/7 'DiigoBrowser' => 'DiigoBrowser', // http://www.puffinbrowser.com/index.php 'Puffin' => 'Puffin', // http://mercury-browser.com/index.html 'Mercury' => '\bMercury\b', // http://en.wikipedia.org/wiki/Obigo_Browser 'ObigoBrowser' => 'Obigo', // http://en.wikipedia.org/wiki/NetFront 'NetFront' => 'NF-Browser', // @reference: http://en.wikipedia.org/wiki/Minimo // http://en.wikipedia.org/wiki/Vision_Mobile_Browser 'GenericBrowser' => 'NokiaBrowser|OviBrowser|OneBrowser|TwonkyBeamBrowser|SEMC.*Browser|FlyFlow|Minimo|NetFront|Novarra-Vision|MQQBrowser|MicroMessenger', // @reference: https://en.wikipedia.org/wiki/Pale_Moon_(web_browser) 'PaleMoon' => 'Android.*PaleMoon|Mobile.*PaleMoon', ); /** * Utilities. * * @var array */ protected static $utilities = array( // Experimental. When a mobile device wants to switch to 'Desktop Mode'. // http://scottcate.com/technology/windows-phone-8-ie10-desktop-or-mobile/ // https://github.com/serbanghita/Mobile-Detect/issues/57#issuecomment-15024011 // https://developers.facebook.com/docs/sharing/best-practices 'Bot' => 'Googlebot|facebookexternalhit|AdsBot-Google|Google Keyword Suggestion|Facebot|YandexBot|YandexMobileBot|bingbot|ia_archiver|AhrefsBot|Ezooms|GSLFbot|WBSearchBot|Twitterbot|TweetmemeBot|Twikle|PaperLiBot|Wotbox|UnwindFetchor|Exabot|MJ12bot|YandexImages|TurnitinBot|Pingdom', 'MobileBot' => 'Googlebot-Mobile|AdsBot-Google-Mobile|YahooSeeker/M1A1-R2D2', 'DesktopMode' => 'WPDesktop', 'TV' => 'SonyDTV|HbbTV', // experimental 'WebKit' => '(webkit)[ /]([\w.]+)', // @todo: Include JXD consoles. 'Console' => '\b(Nintendo|Nintendo WiiU|Nintendo 3DS|PLAYSTATION|Xbox)\b', 'Watch' => 'SM-V700', ); /** * All possible HTTP headers that represent the * User-Agent string. * * @var array */ protected static $uaHttpHeaders = array( // The default User-Agent string. 'HTTP_USER_AGENT', // Header can occur on devices using Opera Mini. 'HTTP_X_OPERAMINI_PHONE_UA', // Vodafone specific header: http://www.seoprinciple.com/mobile-web-community-still-angry-at-vodafone/24/ 'HTTP_X_DEVICE_USER_AGENT', 'HTTP_X_ORIGINAL_USER_AGENT', 'HTTP_X_SKYFIRE_PHONE', 'HTTP_X_BOLT_PHONE_UA', 'HTTP_DEVICE_STOCK_UA', 'HTTP_X_UCBROWSER_DEVICE_UA' ); /** * The individual segments that could exist in a User-Agent string. VER refers to the regular * expression defined in the constant self::VER. * * @var array */ protected static $properties = array( // Build 'Mobile' => 'Mobile/[VER]', 'Build' => 'Build/[VER]', 'Version' => 'Version/[VER]', 'VendorID' => 'VendorID/[VER]', // Devices 'iPad' => 'iPad.*CPU[a-z ]+[VER]', 'iPhone' => 'iPhone.*CPU[a-z ]+[VER]', 'iPod' => 'iPod.*CPU[a-z ]+[VER]', //'BlackBerry' => array('BlackBerry[VER]', 'BlackBerry [VER];'), 'Kindle' => 'Kindle/[VER]', // Browser 'Chrome' => array('Chrome/[VER]', 'CriOS/[VER]', 'CrMo/[VER]'), 'Coast' => array('Coast/[VER]'), 'Dolfin' => 'Dolfin/[VER]', // @reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent/Firefox 'Firefox' => array('Firefox/[VER]', 'FxiOS/[VER]'), 'Fennec' => 'Fennec/[VER]', // http://msdn.microsoft.com/en-us/library/ms537503(v=vs.85).aspx // https://msdn.microsoft.com/en-us/library/ie/hh869301(v=vs.85).aspx 'Edge' => 'Edge/[VER]', 'IE' => array('IEMobile/[VER];', 'IEMobile [VER]', 'MSIE [VER];', 'Trident/[0-9.]+;.*rv:[VER]'), // http://en.wikipedia.org/wiki/NetFront 'NetFront' => 'NetFront/[VER]', 'NokiaBrowser' => 'NokiaBrowser/[VER]', 'Opera' => array( ' OPR/[VER]', 'Opera Mini/[VER]', 'Version/[VER]' ), 'Opera Mini' => 'Opera Mini/[VER]', 'Opera Mobi' => 'Version/[VER]', 'UCBrowser' => array( 'UCWEB[VER]', 'UC.*Browser/[VER]' ), 'MQQBrowser' => 'MQQBrowser/[VER]', 'MicroMessenger' => 'MicroMessenger/[VER]', 'baiduboxapp' => 'baiduboxapp/[VER]', 'baidubrowser' => 'baidubrowser/[VER]', 'SamsungBrowser' => 'SamsungBrowser/[VER]', 'Iron' => 'Iron/[VER]', // @note: Safari 7534.48.3 is actually Version 5.1. // @note: On BlackBerry the Version is overwriten by the OS. 'Safari' => array( 'Version/[VER]', 'Safari/[VER]' ), 'Skyfire' => 'Skyfire/[VER]', 'Tizen' => 'Tizen/[VER]', 'Webkit' => 'webkit[ /][VER]', 'PaleMoon' => 'PaleMoon/[VER]', // Engine 'Gecko' => 'Gecko/[VER]', 'Trident' => 'Trident/[VER]', 'Presto' => 'Presto/[VER]', 'Goanna' => 'Goanna/[VER]', // OS 'iOS' => ' \bi?OS\b [VER][ ;]{1}', 'Android' => 'Android [VER]', 'BlackBerry' => array('BlackBerry[\w]+/[VER]', 'BlackBerry.*Version/[VER]', 'Version/[VER]'), 'BREW' => 'BREW [VER]', 'Java' => 'Java/[VER]', // @reference: http://windowsteamblog.com/windows_phone/b/wpdev/archive/2011/08/29/introducing-the-ie9-on-windows-phone-mango-user-agent-string.aspx // @reference: http://en.wikipedia.org/wiki/Windows_NT#Releases 'Windows Phone OS' => array( 'Windows Phone OS [VER]', 'Windows Phone [VER]'), 'Windows Phone' => 'Windows Phone [VER]', 'Windows CE' => 'Windows CE/[VER]', // http://social.msdn.microsoft.com/Forums/en-US/windowsdeveloperpreviewgeneral/thread/6be392da-4d2f-41b4-8354-8dcee20c85cd 'Windows NT' => 'Windows NT [VER]', 'Symbian' => array('SymbianOS/[VER]', 'Symbian/[VER]'), 'webOS' => array('webOS/[VER]', 'hpwOS/[VER];'), ); /** * Construct an instance of this class. * * @param array $headers Specify the headers as injection. Should be PHP _SERVER flavored. * If left empty, will use the global _SERVER['HTTP_*'] vars instead. * @param string $userAgent Inject the User-Agent header. If null, will use HTTP_USER_AGENT * from the $headers array instead. */ public function __construct( array $headers = null, $userAgent = null ) { $this->setHttpHeaders($headers); $this->setUserAgent($userAgent); } /** * Get the current script version. * This is useful for the demo.php file, * so people can check on what version they are testing * for mobile devices. * * @return string The version number in semantic version format. */ public static function getScriptVersion() { return self::VERSION; } /** * Set the HTTP Headers. Must be PHP-flavored. This method will reset existing headers. * * @param array $httpHeaders The headers to set. If null, then using PHP's _SERVER to extract * the headers. The default null is left for backwards compatibility. */ public function setHttpHeaders($httpHeaders = null) { // use global _SERVER if $httpHeaders aren't defined if (!is_array($httpHeaders) || !count($httpHeaders)) { $httpHeaders = $_SERVER; } // clear existing headers $this->httpHeaders = array(); // Only save HTTP headers. In PHP land, that means only _SERVER vars that // start with HTTP_. foreach ($httpHeaders as $key => $value) { if (substr($key, 0, 5) === 'HTTP_') { $this->httpHeaders[$key] = $value; } } // In case we're dealing with CloudFront, we need to know. $this->setCfHeaders($httpHeaders); } /** * Retrieves the HTTP headers. * * @return array */ public function getHttpHeaders() { return $this->httpHeaders; } /** * Retrieves a particular header. If it doesn't exist, no exception/error is caused. * Simply null is returned. * * @param string $header The name of the header to retrieve. Can be HTTP compliant such as * "User-Agent" or "X-Device-User-Agent" or can be php-esque with the * all-caps, HTTP_ prefixed, underscore seperated awesomeness. * * @return string|null The value of the header. */ public function getHttpHeader($header) { // are we using PHP-flavored headers? if (strpos($header, '_') === false) { $header = str_replace('-', '_', $header); $header = strtoupper($header); } // test the alternate, too $altHeader = 'HTTP_' . $header; //Test both the regular and the HTTP_ prefix if (isset($this->httpHeaders[$header])) { return $this->httpHeaders[$header]; } elseif (isset($this->httpHeaders[$altHeader])) { return $this->httpHeaders[$altHeader]; } return null; } public function getMobileHeaders() { return self::$mobileHeaders; } /** * Get all possible HTTP headers that * can contain the User-Agent string. * * @return array List of HTTP headers. */ public function getUaHttpHeaders() { return self::$uaHttpHeaders; } /** * Set CloudFront headers * http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html#header-caching-web-device * * @param array $cfHeaders List of HTTP headers * * @return boolean If there were CloudFront headers to be set */ public function setCfHeaders($cfHeaders = null) { // use global _SERVER if $cfHeaders aren't defined if (!is_array($cfHeaders) || !count($cfHeaders)) { $cfHeaders = $_SERVER; } // clear existing headers $this->cloudfrontHeaders = array(); // Only save CLOUDFRONT headers. In PHP land, that means only _SERVER vars that // start with cloudfront-. $response = false; foreach ($cfHeaders as $key => $value) { if (substr(strtolower($key), 0, 16) === 'http_cloudfront_') { $this->cloudfrontHeaders[strtoupper($key)] = $value; $response = true; } } return $response; } /** * Retrieves the cloudfront headers. * * @return array */ public function getCfHeaders() { return $this->cloudfrontHeaders; } /** * @param string $userAgent * @return string */ private function prepareUserAgent($userAgent) { $userAgent = trim($userAgent); $userAgent = substr($userAgent, 0, 500); return $userAgent; } /** * Set the User-Agent to be used. * * @param string $userAgent The user agent string to set. * * @return string|null */ public function setUserAgent($userAgent = null) { // Invalidate cache due to #375 $this->cache = array(); if (false === empty($userAgent)) { return $this->userAgent = $this->prepareUserAgent($userAgent); } else { $this->userAgent = null; foreach ($this->getUaHttpHeaders() as $altHeader) { if (false === empty($this->httpHeaders[$altHeader])) { // @todo: should use getHttpHeader(), but it would be slow. (Serban) $this->userAgent .= $this->httpHeaders[$altHeader] . " "; } } if (!empty($this->userAgent)) { return $this->userAgent = $this->prepareUserAgent($this->userAgent); } } if (count($this->getCfHeaders()) > 0) { return $this->userAgent = 'Amazon CloudFront'; } return $this->userAgent = null; } /** * Retrieve the User-Agent. * * @return string|null The user agent if it's set. */ public function getUserAgent() { return $this->userAgent; } /** * Set the detection type. Must be one of self::DETECTION_TYPE_MOBILE or * self::DETECTION_TYPE_EXTENDED. Otherwise, nothing is set. * * @deprecated since version 2.6.9 * * @param string $type The type. Must be a self::DETECTION_TYPE_* constant. The default * parameter is null which will default to self::DETECTION_TYPE_MOBILE. */ public function setDetectionType($type = null) { if ($type === null) { $type = self::DETECTION_TYPE_MOBILE; } if ($type !== self::DETECTION_TYPE_MOBILE && $type !== self::DETECTION_TYPE_EXTENDED) { return; } $this->detectionType = $type; } public function getMatchingRegex() { return $this->matchingRegex; } public function getMatchesArray() { return $this->matchesArray; } /** * Retrieve the list of known phone devices. * * @return array List of phone devices. */ public static function getPhoneDevices() { return self::$phoneDevices; } /** * Retrieve the list of known tablet devices. * * @return array List of tablet devices. */ public static function getTabletDevices() { return self::$tabletDevices; } /** * Alias for getBrowsers() method. * * @return array List of user agents. */ public static function getUserAgents() { return self::getBrowsers(); } /** * Retrieve the list of known browsers. Specifically, the user agents. * * @return array List of browsers / user agents. */ public static function getBrowsers() { return self::$browsers; } /** * Retrieve the list of known utilities. * * @return array List of utilities. */ public static function getUtilities() { return self::$utilities; } /** * Method gets the mobile detection rules. This method is used for the magic methods $detect->is*(). * * @deprecated since version 2.6.9 * * @return array All the rules (but not extended). */ public static function getMobileDetectionRules() { static $rules; if (!$rules) { $rules = array_merge( self::$phoneDevices, self::$tabletDevices, self::$operatingSystems, self::$browsers ); } return $rules; } /** * Method gets the mobile detection rules + utilities. * The reason this is separate is because utilities rules * don't necessary imply mobile. This method is used inside * the new $detect->is('stuff') method. * * @deprecated since version 2.6.9 * * @return array All the rules + extended. */ public function getMobileDetectionRulesExtended() { static $rules; if (!$rules) { // Merge all rules together. $rules = array_merge( self::$phoneDevices, self::$tabletDevices, self::$operatingSystems, self::$browsers, self::$utilities ); } return $rules; } /** * Retrieve the current set of rules. * * @deprecated since version 2.6.9 * * @return array */ public function getRules() { if ($this->detectionType == self::DETECTION_TYPE_EXTENDED) { return self::getMobileDetectionRulesExtended(); } else { return self::getMobileDetectionRules(); } } /** * Retrieve the list of mobile operating systems. * * @return array The list of mobile operating systems. */ public static function getOperatingSystems() { return self::$operatingSystems; } /** * Check the HTTP headers for signs of mobile. * This is the fastest mobile check possible; it's used * inside isMobile() method. * * @return bool */ public function checkHttpHeadersForMobile() { foreach ($this->getMobileHeaders() as $mobileHeader => $matchType) { if (isset($this->httpHeaders[$mobileHeader])) { if (is_array($matchType['matches'])) { foreach ($matchType['matches'] as $_match) { if (strpos($this->httpHeaders[$mobileHeader], $_match) !== false) { return true; } } return false; } else { return true; } } } return false; } /** * Magic overloading method. * * @method boolean is[...]() * @param string $name * @param array $arguments * @return mixed * @throws BadMethodCallException when the method doesn't exist and doesn't start with 'is' */ public function __call($name, $arguments) { // make sure the name starts with 'is', otherwise if (substr($name, 0, 2) !== 'is') { throw new BadMethodCallException("No such method exists: $name"); } $this->setDetectionType(self::DETECTION_TYPE_MOBILE); $key = substr($name, 2); return $this->matchUAAgainstKey($key); } /** * Find a detection rule that matches the current User-agent. * * @param null $userAgent deprecated * @return boolean */ protected function matchDetectionRulesAgainstUA($userAgent = null) { // Begin general search. foreach ($this->getRules() as $_regex) { if (empty($_regex)) { continue; } if ($this->match($_regex, $userAgent)) { return true; } } return false; } /** * Search for a certain key in the rules array. * If the key is found then try to match the corresponding * regex against the User-Agent. * * @param string $key * * @return boolean */ protected function matchUAAgainstKey($key) { // Make the keys lowercase so we can match: isIphone(), isiPhone(), isiphone(), etc. $key = strtolower($key); if (false === isset($this->cache[$key])) { // change the keys to lower case $_rules = array_change_key_case($this->getRules()); if (false === empty($_rules[$key])) { $this->cache[$key] = $this->match($_rules[$key]); } if (false === isset($this->cache[$key])) { $this->cache[$key] = false; } } return $this->cache[$key]; } /** * Check if the device is mobile. * Returns true if any type of mobile device detected, including special ones * @param null $userAgent deprecated * @param null $httpHeaders deprecated * @return bool */ public function isMobile($userAgent = null, $httpHeaders = null) { if ($httpHeaders) { $this->setHttpHeaders($httpHeaders); } if ($userAgent) { $this->setUserAgent($userAgent); } // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront' if ($this->getUserAgent() === 'Amazon CloudFront') { $cfHeaders = $this->getCfHeaders(); if(array_key_exists('HTTP_CLOUDFRONT_IS_MOBILE_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_MOBILE_VIEWER'] === 'true') { return true; } } $this->setDetectionType(self::DETECTION_TYPE_MOBILE); if ($this->checkHttpHeadersForMobile()) { return true; } else { return $this->matchDetectionRulesAgainstUA(); } } /** * Check if the device is a tablet. * Return true if any type of tablet device is detected. * * @param string $userAgent deprecated * @param array $httpHeaders deprecated * @return bool */ public function isTablet($userAgent = null, $httpHeaders = null) { // Check specifically for cloudfront headers if the useragent === 'Amazon CloudFront' if ($this->getUserAgent() === 'Amazon CloudFront') { $cfHeaders = $this->getCfHeaders(); if(array_key_exists('HTTP_CLOUDFRONT_IS_TABLET_VIEWER', $cfHeaders) && $cfHeaders['HTTP_CLOUDFRONT_IS_TABLET_VIEWER'] === 'true') { return true; } } $this->setDetectionType(self::DETECTION_TYPE_MOBILE); foreach (self::$tabletDevices as $_regex) { if ($this->match($_regex, $userAgent)) { return true; } } return false; } /** * This method checks for a certain property in the * userAgent. * @todo: The httpHeaders part is not yet used. * * @param string $key * @param string $userAgent deprecated * @param string $httpHeaders deprecated * @return bool|int|null */ public function is($key, $userAgent = null, $httpHeaders = null) { // Set the UA and HTTP headers only if needed (eg. batch mode). if ($httpHeaders) { $this->setHttpHeaders($httpHeaders); } if ($userAgent) { $this->setUserAgent($userAgent); } $this->setDetectionType(self::DETECTION_TYPE_EXTENDED); return $this->matchUAAgainstKey($key); } /** * Some detection rules are relative (not standard), * because of the diversity of devices, vendors and * their conventions in representing the User-Agent or * the HTTP headers. * * This method will be used to check custom regexes against * the User-Agent string. * * @param $regex * @param string $userAgent * @return bool * * @todo: search in the HTTP headers too. */ public function match($regex, $userAgent = null) { $match = (bool) preg_match(sprintf('#%s#is', $regex), (false === empty($userAgent) ? $userAgent : $this->userAgent), $matches); // If positive match is found, store the results for debug. if ($match) { $this->matchingRegex = $regex; $this->matchesArray = $matches; } return $match; } /** * Get the properties array. * * @return array */ public static function getProperties() { return self::$properties; } /** * Prepare the version number. * * @todo Remove the error supression from str_replace() call. * * @param string $ver The string version, like "2.6.21.2152"; * * @return float */ public function prepareVersionNo($ver) { $ver = str_replace(array('_', ' ', '/'), '.', $ver); $arrVer = explode('.', $ver, 2); if (isset($arrVer[1])) { $arrVer[1] = @str_replace('.', '', $arrVer[1]); // @todo: treat strings versions. } return (float) implode('.', $arrVer); } /** * Check the version of the given property in the User-Agent. * Will return a float number. (eg. 2_0 will return 2.0, 4.3.1 will return 4.31) * * @param string $propertyName The name of the property. See self::getProperties() array * keys for all possible properties. * @param string $type Either self::VERSION_TYPE_STRING to get a string value or * self::VERSION_TYPE_FLOAT indicating a float value. This parameter * is optional and defaults to self::VERSION_TYPE_STRING. Passing an * invalid parameter will default to the this type as well. * * @return string|float The version of the property we are trying to extract. */ public function version($propertyName, $type = self::VERSION_TYPE_STRING) { if (empty($propertyName)) { return false; } // set the $type to the default if we don't recognize the type if ($type !== self::VERSION_TYPE_STRING && $type !== self::VERSION_TYPE_FLOAT) { $type = self::VERSION_TYPE_STRING; } $properties = self::getProperties(); // Check if the property exists in the properties array. if (true === isset($properties[$propertyName])) { // Prepare the pattern to be matched. // Make sure we always deal with an array (string is converted). $properties[$propertyName] = (array) $properties[$propertyName]; foreach ($properties[$propertyName] as $propertyMatchString) { $propertyPattern = str_replace('[VER]', self::VER, $propertyMatchString); // Identify and extract the version. preg_match(sprintf('#%s#is', $propertyPattern), $this->userAgent, $match); if (false === empty($match[1])) { $version = ($type == self::VERSION_TYPE_FLOAT ? $this->prepareVersionNo($match[1]) : $match[1]); return $version; } } } return false; } /** * Retrieve the mobile grading, using self::MOBILE_GRADE_* constants. * * @return string One of the self::MOBILE_GRADE_* constants. */ public function mobileGrade() { $isMobile = $this->isMobile(); if ( // Apple iOS 4-7.0 – Tested on the original iPad (4.3 / 5.0), iPad 2 (4.3 / 5.1 / 6.1), iPad 3 (5.1 / 6.0), iPad Mini (6.1), iPad Retina (7.0), iPhone 3GS (4.3), iPhone 4 (4.3 / 5.1), iPhone 4S (5.1 / 6.0), iPhone 5 (6.0), and iPhone 5S (7.0) $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) >= 4.3 || $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) >= 4.3 || $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) >= 4.3 || // Android 2.1-2.3 - Tested on the HTC Incredible (2.2), original Droid (2.2), HTC Aria (2.1), Google Nexus S (2.3). Functional on 1.5 & 1.6 but performance may be sluggish, tested on Google G1 (1.5) // Android 3.1 (Honeycomb) - Tested on the Samsung Galaxy Tab 10.1 and Motorola XOOM // Android 4.0 (ICS) - Tested on a Galaxy Nexus. Note: transition performance can be poor on upgraded devices // Android 4.1 (Jelly Bean) - Tested on a Galaxy Nexus and Galaxy 7 ( $this->version('Android', self::VERSION_TYPE_FLOAT)>2.1 && $this->is('Webkit') ) || // Windows Phone 7.5-8 - Tested on the HTC Surround (7.5), HTC Trophy (7.5), LG-E900 (7.5), Nokia 800 (7.8), HTC Mazaa (7.8), Nokia Lumia 520 (8), Nokia Lumia 920 (8), HTC 8x (8) $this->version('Windows Phone OS', self::VERSION_TYPE_FLOAT) >= 7.5 || // Tested on the Torch 9800 (6) and Style 9670 (6), BlackBerry® Torch 9810 (7), BlackBerry Z10 (10) $this->is('BlackBerry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 6.0 || // Blackberry Playbook (1.0-2.0) - Tested on PlayBook $this->match('Playbook.*Tablet') || // Palm WebOS (1.4-3.0) - Tested on the Palm Pixi (1.4), Pre (1.4), Pre 2 (2.0), HP TouchPad (3.0) ( $this->version('webOS', self::VERSION_TYPE_FLOAT) >= 1.4 && $this->match('Palm|Pre|Pixi') ) || // Palm WebOS 3.0 - Tested on HP TouchPad $this->match('hp.*TouchPad') || // Firefox Mobile 18 - Tested on Android 2.3 and 4.1 devices ( $this->is('Firefox') && $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 18 ) || // Chrome for Android - Tested on Android 4.0, 4.1 device ( $this->is('Chrome') && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 4.0 ) || // Skyfire 4.1 - Tested on Android 2.3 device ( $this->is('Skyfire') && $this->version('Skyfire', self::VERSION_TYPE_FLOAT) >= 4.1 && $this->is('AndroidOS') && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) || // Opera Mobile 11.5-12: Tested on Android 2.3 ( $this->is('Opera') && $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11.5 && $this->is('AndroidOS') ) || // Meego 1.2 - Tested on Nokia 950 and N9 $this->is('MeeGoOS') || // Tizen (pre-release) - Tested on early hardware $this->is('Tizen') || // Samsung Bada 2.0 - Tested on a Samsung Wave 3, Dolphin browser // @todo: more tests here! $this->is('Dolfin') && $this->version('Bada', self::VERSION_TYPE_FLOAT) >= 2.0 || // UC Browser - Tested on Android 2.3 device ( ($this->is('UC Browser') || $this->is('Dolfin')) && $this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 ) || // Kindle 3 and Fire - Tested on the built-in WebKit browser for each ( $this->match('Kindle Fire') || $this->is('Kindle') && $this->version('Kindle', self::VERSION_TYPE_FLOAT) >= 3.0 ) || // Nook Color 1.4.1 - Tested on original Nook Color, not Nook Tablet $this->is('AndroidOS') && $this->is('NookTablet') || // Chrome Desktop 16-24 - Tested on OS X 10.7 and Windows 7 $this->version('Chrome', self::VERSION_TYPE_FLOAT) >= 16 && !$isMobile || // Safari Desktop 5-6 - Tested on OS X 10.7 and Windows 7 $this->version('Safari', self::VERSION_TYPE_FLOAT) >= 5.0 && !$isMobile || // Firefox Desktop 10-18 - Tested on OS X 10.7 and Windows 7 $this->version('Firefox', self::VERSION_TYPE_FLOAT) >= 10.0 && !$isMobile || // Internet Explorer 7-9 - Tested on Windows XP, Vista and 7 $this->version('IE', self::VERSION_TYPE_FLOAT) >= 7.0 && !$isMobile || // Opera Desktop 10-12 - Tested on OS X 10.7 and Windows 7 $this->version('Opera', self::VERSION_TYPE_FLOAT) >= 10 && !$isMobile ){ return self::MOBILE_GRADE_A; } if ( $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT)<4.3 || $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT)<4.3 || $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT)<4.3 || // Blackberry 5.0: Tested on the Storm 2 9550, Bold 9770 $this->is('Blackberry') && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) >= 5 && $this->version('BlackBerry', self::VERSION_TYPE_FLOAT)<6 || //Opera Mini (5.0-6.5) - Tested on iOS 3.2/4.3 and Android 2.3 ($this->version('Opera Mini', self::VERSION_TYPE_FLOAT) >= 5.0 && $this->version('Opera Mini', self::VERSION_TYPE_FLOAT) <= 7.0 && ($this->version('Android', self::VERSION_TYPE_FLOAT) >= 2.3 || $this->is('iOS')) ) || // Nokia Symbian^3 - Tested on Nokia N8 (Symbian^3), C7 (Symbian^3), also works on N97 (Symbian^1) $this->match('NokiaN8|NokiaC7|N97.*Series60|Symbian/3') || // @todo: report this (tested on Nokia N71) $this->version('Opera Mobi', self::VERSION_TYPE_FLOAT) >= 11 && $this->is('SymbianOS') ){ return self::MOBILE_GRADE_B; } if ( // Blackberry 4.x - Tested on the Curve 8330 $this->version('BlackBerry', self::VERSION_TYPE_FLOAT) <= 5.0 || // Windows Mobile - Tested on the HTC Leo (WinMo 5.2) $this->match('MSIEMobile|Windows CE.*Mobile') || $this->version('Windows Mobile', self::VERSION_TYPE_FLOAT) <= 5.2 || // Tested on original iPhone (3.1), iPhone 3 (3.2) $this->is('iOS') && $this->version('iPad', self::VERSION_TYPE_FLOAT) <= 3.2 || $this->is('iOS') && $this->version('iPhone', self::VERSION_TYPE_FLOAT) <= 3.2 || $this->is('iOS') && $this->version('iPod', self::VERSION_TYPE_FLOAT) <= 3.2 || // Internet Explorer 7 and older - Tested on Windows XP $this->version('IE', self::VERSION_TYPE_FLOAT) <= 7.0 && !$isMobile ){ return self::MOBILE_GRADE_C; } // All older smartphone platforms and featurephones - Any device that doesn't support media queries // will receive the basic, C grade experience. return self::MOBILE_GRADE_C; } } PK!cA--welcome_header.phpnu[ TWCC Digital Development Business Service

Loading...

session->userdata('id') > 0 ){ ?>
PK!apply_certificate.phpnu[PK! 'ZAstudents_footer1.phpnu[
PK!X!Ғstudents_footer.phpnu[
PK!.DDportalHead.phpnu[ Admin
PK!u%JmJmofficerHeader.phpnu[ Officer
db->where('id',$this->session->userdata('id')); foreach($this->db->get('personalDetails')->result() as $profile){ $email = $profile->email; $fullname = $profile->firstName.' '.$profile->middleName.' '.$profile->lastName; if($profile->photo == NULL){ $photo = "mtu.jpg"; }else{ $photo = $profile->photo; } } ?>
PK!i printingFooter.phpnu[
PK!&printingHeader.phpnu[ Admin
PK!ʇk k officerFooter.phpnu[
PK!nportalFooter.phpnu[
All Rights Reserved.
PK!r"sUsUportalHeader.phpnu[ Portal
The United Republic of Tanzania

Ministry of Defence and National Service

INTRANET PORTAL

This is example text to build on the card title and make up the bulk of the card's content.


UPCOMING EVENTS
    db->where('no>=',date('m'))->limit(3)->get('portalEvents')->result() as $row){ ?>
  •    
    name;?>
    day.', '.$row->date;?>

PK!I++header.blade.phpnu[ Client Area
PK!.3GGlxml-version.hnu[#ifndef LXML_VERSION_STRING #define LXML_VERSION_STRING "4.9.2" #endif PK!bBTT xinclude.pxdnu[from lxml.includes.tree cimport xmlDoc, xmlNode cdef extern from "libxml/xinclude.h": ctypedef struct xmlXIncludeCtxt cdef int xmlXIncludeProcess(xmlDoc* doc) nogil cdef int xmlXIncludeProcessFlags(xmlDoc* doc, int parser_opts) nogil cdef int xmlXIncludeProcessTree(xmlNode* doc) nogil cdef int xmlXIncludeProcessTreeFlags(xmlNode* doc, int parser_opts) nogil # libxml2 >= 2.7.4 cdef int xmlXIncludeProcessTreeFlagsData( xmlNode* doc, int parser_opts, void* data) nogil cdef xmlXIncludeCtxt* xmlXIncludeNewContext(xmlDoc* doc) nogil cdef int xmlXIncludeProcessNode(xmlXIncludeCtxt* ctxt, xmlNode* node) nogil cdef int xmlXIncludeSetFlags(xmlXIncludeCtxt* ctxt, int flags) nogil # libxml2 >= 2.6.27 cdef int xmlXIncludeProcessFlagsData( xmlDoc* doc, int flags, void* data) nogil PK!ӳ*-libexslt/__pycache__/__init__.cpython-311.pycnu[ idS)Nr/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib64/python3.11/site-packages/lxml/includes/libexslt/__init__.pyrsrPK!]$libexslt/exsltconfig.hnu[/* * exsltconfig.h: compile-time version information for the EXSLT library * * See Copyright for the status of this software. * * daniel@veillard.com */ #ifndef __XML_EXSLTCONFIG_H__ #define __XML_EXSLTCONFIG_H__ #ifdef __cplusplus extern "C" { #endif /** * LIBEXSLT_DOTTED_VERSION: * * the version string like "1.2.3" */ #define LIBEXSLT_DOTTED_VERSION "0.8.20" /** * LIBEXSLT_VERSION: * * the version number: 1.2.3 value is 10203 */ #define LIBEXSLT_VERSION 820 /** * LIBEXSLT_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ #define LIBEXSLT_VERSION_STRING "820" /** * LIBEXSLT_VERSION_EXTRA: * * extra version information, used to show a CVS compilation */ #define LIBEXSLT_VERSION_EXTRA "" /** * WITH_CRYPTO: * * Whether crypto support is configured into exslt */ #if 0 #define EXSLT_CRYPTO_ENABLED #endif /** * ATTRIBUTE_UNUSED: * * This macro is used to flag unused function parameters to GCC */ #ifdef __GNUC__ #ifndef ATTRIBUTE_UNUSED #define ATTRIBUTE_UNUSED __attribute__((unused)) #endif #else #define ATTRIBUTE_UNUSED #endif #ifdef __cplusplus } #endif #endif /* __XML_EXSLTCONFIG_H__ */ PK!2c* * libexslt/exslt.hnu[/* * Summary: main header file * * Copy: See Copyright for the status of this software. */ #ifndef __EXSLT_H__ #define __EXSLT_H__ #include #include #include "exsltexports.h" #include #ifdef __cplusplus extern "C" { #endif EXSLTPUBVAR const char *exsltLibraryVersion; EXSLTPUBVAR const int exsltLibexsltVersion; EXSLTPUBVAR const int exsltLibxsltVersion; EXSLTPUBVAR const int exsltLibxmlVersion; /** * EXSLT_COMMON_NAMESPACE: * * Namespace for EXSLT common functions */ #define EXSLT_COMMON_NAMESPACE ((const xmlChar *) "http://exslt.org/common") /** * EXSLT_CRYPTO_NAMESPACE: * * Namespace for EXSLT crypto functions */ #define EXSLT_CRYPTO_NAMESPACE ((const xmlChar *) "http://exslt.org/crypto") /** * EXSLT_MATH_NAMESPACE: * * Namespace for EXSLT math functions */ #define EXSLT_MATH_NAMESPACE ((const xmlChar *) "http://exslt.org/math") /** * EXSLT_SETS_NAMESPACE: * * Namespace for EXSLT set functions */ #define EXSLT_SETS_NAMESPACE ((const xmlChar *) "http://exslt.org/sets") /** * EXSLT_FUNCTIONS_NAMESPACE: * * Namespace for EXSLT functions extension functions */ #define EXSLT_FUNCTIONS_NAMESPACE ((const xmlChar *) "http://exslt.org/functions") /** * EXSLT_STRINGS_NAMESPACE: * * Namespace for EXSLT strings functions */ #define EXSLT_STRINGS_NAMESPACE ((const xmlChar *) "http://exslt.org/strings") /** * EXSLT_DATE_NAMESPACE: * * Namespace for EXSLT date functions */ #define EXSLT_DATE_NAMESPACE ((const xmlChar *) "http://exslt.org/dates-and-times") /** * EXSLT_DYNAMIC_NAMESPACE: * * Namespace for EXSLT dynamic functions */ #define EXSLT_DYNAMIC_NAMESPACE ((const xmlChar *) "http://exslt.org/dynamic") /** * SAXON_NAMESPACE: * * Namespace for SAXON extensions functions */ #define SAXON_NAMESPACE ((const xmlChar *) "http://icl.com/saxon") EXSLTPUBFUN void EXSLTCALL exsltCommonRegister (void); #ifdef EXSLT_CRYPTO_ENABLED EXSLTPUBFUN void EXSLTCALL exsltCryptoRegister (void); #endif EXSLTPUBFUN void EXSLTCALL exsltMathRegister (void); EXSLTPUBFUN void EXSLTCALL exsltSetsRegister (void); EXSLTPUBFUN void EXSLTCALL exsltFuncRegister (void); EXSLTPUBFUN void EXSLTCALL exsltStrRegister (void); EXSLTPUBFUN void EXSLTCALL exsltDateRegister (void); EXSLTPUBFUN void EXSLTCALL exsltSaxonRegister (void); EXSLTPUBFUN void EXSLTCALL exsltDynRegister(void); EXSLTPUBFUN void EXSLTCALL exsltRegisterAll (void); EXSLTPUBFUN int EXSLTCALL exsltDateXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix); EXSLTPUBFUN int EXSLTCALL exsltMathXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix); EXSLTPUBFUN int EXSLTCALL exsltSetsXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix); EXSLTPUBFUN int EXSLTCALL exsltStrXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix); #ifdef __cplusplus } #endif #endif /* __EXSLT_H__ */ PK!"[ [ libexslt/exsltexports.hnu[/* * Summary: macros for marking symbols as exportable/importable. * * Copy: See Copyright for the status of this software. * * Author: Igor Zlatkovic */ #ifndef __EXSLT_EXPORTS_H__ #define __EXSLT_EXPORTS_H__ /** * EXSLTPUBFUN, EXSLTPUBVAR, EXSLTCALL * * Macros which declare an exportable function, an exportable variable and * the calling convention used for functions. * * Please use an extra block for every platform/compiler combination when * modifying this, rather than overlong #ifdef lines. This helps * readability as well as the fact that different compilers on the same * platform might need different definitions. */ /** * EXSLTPUBFUN: * * Macros which declare an exportable function */ #define EXSLTPUBFUN /** * EXSLTPUBVAR: * * Macros which declare an exportable variable */ #define EXSLTPUBVAR extern /** * EXSLTCALL: * * Macros which declare the called convention for exported functions */ #define EXSLTCALL /** DOC_DISABLE */ /* Windows platform with MS compiler */ #if defined(_WIN32) && defined(_MSC_VER) #undef EXSLTPUBFUN #undef EXSLTPUBVAR #undef EXSLTCALL #if defined(IN_LIBEXSLT) && !defined(LIBEXSLT_STATIC) #define EXSLTPUBFUN __declspec(dllexport) #define EXSLTPUBVAR __declspec(dllexport) #else #define EXSLTPUBFUN #if !defined(LIBEXSLT_STATIC) #define EXSLTPUBVAR __declspec(dllimport) extern #else #define EXSLTPUBVAR extern #endif #endif #define EXSLTCALL __cdecl #if !defined _REENTRANT #define _REENTRANT #endif #endif /* Windows platform with Borland compiler */ #if defined(_WIN32) && defined(__BORLANDC__) #undef EXSLTPUBFUN #undef EXSLTPUBVAR #undef EXSLTCALL #if defined(IN_LIBEXSLT) && !defined(LIBEXSLT_STATIC) #define EXSLTPUBFUN __declspec(dllexport) #define EXSLTPUBVAR __declspec(dllexport) extern #else #define EXSLTPUBFUN #if !defined(LIBEXSLT_STATIC) #define EXSLTPUBVAR __declspec(dllimport) extern #else #define EXSLTPUBVAR extern #endif #endif #define EXSLTCALL __cdecl #if !defined _REENTRANT #define _REENTRANT #endif #endif /* Windows platform with GNU compiler (Mingw) */ #if defined(_WIN32) && defined(__MINGW32__) #undef EXSLTPUBFUN #undef EXSLTPUBVAR #undef EXSLTCALL /* #if defined(IN_LIBEXSLT) && !defined(LIBEXSLT_STATIC) */ #if !defined(LIBEXSLT_STATIC) #define EXSLTPUBFUN __declspec(dllexport) #define EXSLTPUBVAR __declspec(dllexport) extern #else #define EXSLTPUBFUN #if !defined(LIBEXSLT_STATIC) #define EXSLTPUBVAR __declspec(dllimport) extern #else #define EXSLTPUBVAR extern #endif #endif #define EXSLTCALL __cdecl #if !defined _REENTRANT #define _REENTRANT #endif #endif /* Cygwin platform (does not define _WIN32), GNU compiler */ #if defined(__CYGWIN__) #undef EXSLTPUBFUN #undef EXSLTPUBVAR #undef EXSLTCALL #if defined(IN_LIBEXSLT) && !defined(LIBEXSLT_STATIC) #define EXSLTPUBFUN __declspec(dllexport) #define EXSLTPUBVAR __declspec(dllexport) #else #define EXSLTPUBFUN #if !defined(LIBEXSLT_STATIC) #define EXSLTPUBVAR __declspec(dllimport) extern #else #define EXSLTPUBVAR extern #endif #endif #define EXSLTCALL __cdecl #endif /* Compatibility */ #if !defined(LIBEXSLT_PUBLIC) #define LIBEXSLT_PUBLIC EXSLTPUBVAR #endif #endif /* __EXSLT_EXPORTS_H__ */ PK!libexslt/__init__.pynu[PK!ƅ$__pycache__/__init__.cpython-311.pycnu[ idS)Nrx/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib64/python3.11/site-packages/lxml/includes/__init__.pyrsrPK!x&hhschematron.pxdnu[from lxml.includes cimport xmlerror from lxml.includes.tree cimport xmlDoc cdef extern from "libxml/schematron.h": ctypedef struct xmlSchematron ctypedef struct xmlSchematronParserCtxt ctypedef struct xmlSchematronValidCtxt ctypedef enum xmlSchematronValidOptions: XML_SCHEMATRON_OUT_QUIET = 1 # quiet no report XML_SCHEMATRON_OUT_TEXT = 2 # build a textual report XML_SCHEMATRON_OUT_XML = 4 # output SVRL XML_SCHEMATRON_OUT_ERROR = 8 # output via xmlStructuredErrorFunc XML_SCHEMATRON_OUT_FILE = 256 # output to a file descriptor XML_SCHEMATRON_OUT_BUFFER = 512 # output to a buffer XML_SCHEMATRON_OUT_IO = 1024 # output to I/O mechanism cdef xmlSchematronParserCtxt* xmlSchematronNewDocParserCtxt( xmlDoc* doc) nogil cdef xmlSchematronParserCtxt* xmlSchematronNewParserCtxt( char* filename) nogil cdef xmlSchematronValidCtxt* xmlSchematronNewValidCtxt( xmlSchematron* schema, int options) nogil cdef xmlSchematron* xmlSchematronParse(xmlSchematronParserCtxt* ctxt) nogil cdef int xmlSchematronValidateDoc(xmlSchematronValidCtxt* ctxt, xmlDoc* instance) nogil cdef void xmlSchematronFreeParserCtxt(xmlSchematronParserCtxt* ctxt) nogil cdef void xmlSchematronFreeValidCtxt(xmlSchematronValidCtxt* ctxt) nogil cdef void xmlSchematronFree(xmlSchematron* schema) nogil cdef void xmlSchematronSetValidStructuredErrors( xmlSchematronValidCtxt* ctxt, xmlerror.xmlStructuredErrorFunc error_func, void *data) PK!ZT`` config.pxdnu[cdef extern from "etree_defs.h": cdef bint ENABLE_THREADING cdef bint ENABLE_SCHEMATRON PK!VJc dtdvalid.pxdnu[from lxml.includes cimport tree from lxml.includes.tree cimport xmlDoc, xmlDtd cdef extern from "libxml/valid.h" nogil: ctypedef void (*xmlValidityErrorFunc)(void * ctx, const char * msg, ...) ctypedef void (*xmlValidityWarningFunc)(void * ctx, const char * msg, ...) ctypedef struct xmlValidCtxt: void *userData xmlValidityErrorFunc error xmlValidityWarningFunc warning cdef xmlValidCtxt* xmlNewValidCtxt() cdef void xmlFreeValidCtxt(xmlValidCtxt* cur) cdef int xmlValidateDtd(xmlValidCtxt* ctxt, xmlDoc* doc, xmlDtd* dtd) cdef tree.xmlElement* xmlGetDtdElementDesc( xmlDtd* dtd, tree.const_xmlChar* name) PK!k<< etree_defs.hnu[#ifndef HAS_ETREE_DEFS_H #define HAS_ETREE_DEFS_H /* quick check for Python/libxml2/libxslt devel setup */ #include "Python.h" #ifndef PY_VERSION_HEX # error the development package of Python (header files etc.) is not installed correctly #else # if PY_VERSION_HEX < 0x02070000 || PY_MAJOR_VERSION >= 3 && PY_VERSION_HEX < 0x03050000 # error this version of lxml requires Python 2.7, 3.5 or later # endif #endif #include "libxml/xmlversion.h" #ifndef LIBXML_VERSION # error the development package of libxml2 (header files etc.) is not installed correctly #else #if LIBXML_VERSION < 20700 # error minimum required version of libxml2 is 2.7.0 #endif #endif #include "libxslt/xsltconfig.h" #ifndef LIBXSLT_VERSION # error the development package of libxslt (header files etc.) is not installed correctly #else #if LIBXSLT_VERSION < 10123 # error minimum required version of libxslt is 1.1.23 #endif #endif /* v_arg functions */ #define va_int(ap) va_arg(ap, int) #define va_charptr(ap) va_arg(ap, char *) #ifdef PYPY_VERSION # define IS_PYPY 1 #else # define IS_PYPY 0 #endif #if PY_MAJOR_VERSION >= 3 # define IS_PYTHON2 0 /* prefer for special casing Python 2.x */ # define IS_PYTHON3 1 /* avoid */ #else # define IS_PYTHON2 1 # define IS_PYTHON3 0 #endif #if IS_PYTHON2 #ifndef LXML_UNICODE_STRINGS #define LXML_UNICODE_STRINGS 0 #endif #else #undef LXML_UNICODE_STRINGS #define LXML_UNICODE_STRINGS 1 #endif #if !IS_PYPY # define PyWeakref_LockObject(obj) (NULL) #endif /* Threading is not currently supported by PyPy */ #if IS_PYPY # ifndef WITHOUT_THREADING # define WITHOUT_THREADING # endif #endif #if IS_PYPY # undef PyFile_AsFile # define PyFile_AsFile(o) (NULL) # undef PyByteArray_Check # define PyByteArray_Check(o) (0) #elif !IS_PYTHON2 /* Python 3+ doesn't have PyFile_*() anymore */ # define PyFile_AsFile(o) (NULL) #endif #if IS_PYPY # ifndef PyUnicode_FromFormat # define PyUnicode_FromFormat PyString_FromFormat # endif # if !IS_PYTHON2 && !defined(PyBytes_FromFormat) # ifdef PyString_FromFormat # define PyBytes_FromFormat PyString_FromFormat # else #include static PyObject* PyBytes_FromFormat(const char* format, ...) { PyObject *string; va_list vargs; #ifdef HAVE_STDARG_PROTOTYPES va_start(vargs, format); #else va_start(vargs); #endif string = PyUnicode_FromFormatV(format, vargs); va_end(vargs); if (string && PyUnicode_Check(string)) { PyObject *bstring = PyUnicode_AsUTF8String(string); Py_DECREF(string); string = bstring; } if (string && !PyBytes_CheckExact(string)) { Py_DECREF(string); string = NULL; PyErr_SetString(PyExc_TypeError, "String formatting and encoding failed to return bytes object"); } return string; } # endif # endif #endif /* PySlice_GetIndicesEx() has wrong signature in Py<=3.1 */ #if PY_VERSION_HEX >= 0x03020000 # define _lx_PySlice_GetIndicesEx(o, l, b, e, s, sl) PySlice_GetIndicesEx(o, l, b, e, s, sl) #else # define _lx_PySlice_GetIndicesEx(o, l, b, e, s, sl) PySlice_GetIndicesEx(((PySliceObject*)o), l, b, e, s, sl) #endif #ifdef WITHOUT_THREADING # undef PyEval_SaveThread # define PyEval_SaveThread() (NULL) # undef PyEval_RestoreThread # define PyEval_RestoreThread(state) if (state); else {} # undef PyGILState_Ensure # define PyGILState_Ensure() (PyGILState_UNLOCKED) # undef PyGILState_Release # define PyGILState_Release(state) if (state); else {} # undef Py_UNBLOCK_THREADS # define Py_UNBLOCK_THREADS _save = NULL; # undef Py_BLOCK_THREADS # define Py_BLOCK_THREADS if (_save); else {} #endif #ifdef WITHOUT_THREADING # define ENABLE_THREADING 0 #else # define ENABLE_THREADING 1 #endif #if LIBXML_VERSION < 20704 /* FIXME: hack to make new error reporting compile in old libxml2 versions */ # define xmlStructuredErrorContext NULL # define xmlXIncludeProcessTreeFlagsData(n,o,d) xmlXIncludeProcessTreeFlags(n,o) #endif /* schematron was added in libxml2 2.6.21 */ #ifdef LIBXML_SCHEMATRON_ENABLED # define ENABLE_SCHEMATRON 1 #else # define ENABLE_SCHEMATRON 0 # define XML_SCHEMATRON_OUT_QUIET 0 # define XML_SCHEMATRON_OUT_XML 0 # define XML_SCHEMATRON_OUT_ERROR 0 typedef void xmlSchematron; typedef void xmlSchematronParserCtxt; typedef void xmlSchematronValidCtxt; # define xmlSchematronNewDocParserCtxt(doc) NULL # define xmlSchematronNewParserCtxt(file) NULL # define xmlSchematronParse(ctxt) NULL # define xmlSchematronFreeParserCtxt(ctxt) # define xmlSchematronFree(schema) # define xmlSchematronNewValidCtxt(schema, options) NULL # define xmlSchematronValidateDoc(ctxt, doc) 0 # define xmlSchematronFreeValidCtxt(ctxt) # define xmlSchematronSetValidStructuredErrors(ctxt, errorfunc, data) #endif #if LIBXML_VERSION < 20708 # define HTML_PARSE_NODEFDTD 4 #endif #if LIBXML_VERSION < 20900 # define XML_PARSE_BIG_LINES 4194304 #endif #include "libxml/tree.h" #ifndef LIBXML2_NEW_BUFFER typedef xmlBuffer xmlBuf; # define xmlBufContent(buf) xmlBufferContent(buf) # define xmlBufUse(buf) xmlBufferLength(buf) #endif /* libexslt 1.1.25+ support EXSLT functions in XPath */ #if LIBXSLT_VERSION < 10125 #define exsltDateXpathCtxtRegister(ctxt, prefix) #define exsltSetsXpathCtxtRegister(ctxt, prefix) #define exsltMathXpathCtxtRegister(ctxt, prefix) #define exsltStrXpathCtxtRegister(ctxt, prefix) #endif #define LXML_GET_XSLT_ENCODING(result_var, style) XSLT_GET_IMPORT_PTR(result_var, style, encoding) /* work around MSDEV 6.0 */ #if (_MSC_VER == 1200) && (WINVER < 0x0500) long _ftol( double ); //defined by VC6 C libs long _ftol2( double dblSource ) { return _ftol( dblSource ); } #endif #ifdef __GNUC__ /* Test for GCC > 2.95 */ #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) #define unlikely_condition(x) __builtin_expect((x), 0) #else /* __GNUC__ > 2 ... */ #define unlikely_condition(x) (x) #endif /* __GNUC__ > 2 ... */ #else /* __GNUC__ */ #define unlikely_condition(x) (x) #endif /* __GNUC__ */ #ifndef Py_TYPE #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #endif #define PY_NEW(T) \ (((PyTypeObject*)(T))->tp_new( \ (PyTypeObject*)(T), __pyx_empty_tuple, NULL)) #define _fqtypename(o) ((Py_TYPE(o))->tp_name) #define lxml_malloc(count, item_size) \ (unlikely_condition((size_t)(count) > (size_t) (PY_SSIZE_T_MAX / item_size)) ? NULL : \ (PyMem_Malloc((count) * item_size))) #define lxml_realloc(mem, count, item_size) \ (unlikely_condition((size_t)(count) > (size_t) (PY_SSIZE_T_MAX / item_size)) ? NULL : \ (PyMem_Realloc(mem, (count) * item_size))) #define lxml_free(mem) PyMem_Free(mem) #if PY_MAJOR_VERSION < 3 #define _isString(obj) (PyString_CheckExact(obj) || \ PyUnicode_CheckExact(obj) || \ PyType_IsSubtype(Py_TYPE(obj), &PyBaseString_Type)) #else /* builtin subtype type checks are almost as fast as exact checks in Py2.7+ * and Unicode is more common in Py3 */ #define _isString(obj) (PyUnicode_Check(obj) || PyBytes_Check(obj)) #endif #if PY_VERSION_HEX >= 0x03060000 #define lxml_PyOS_FSPath(obj) (PyOS_FSPath(obj)) #else #define lxml_PyOS_FSPath(obj) (NULL) #endif #define _isElement(c_node) \ (((c_node)->type == XML_ELEMENT_NODE) || \ ((c_node)->type == XML_COMMENT_NODE) || \ ((c_node)->type == XML_ENTITY_REF_NODE) || \ ((c_node)->type == XML_PI_NODE)) #define _isElementOrXInclude(c_node) \ (_isElement(c_node) || \ ((c_node)->type == XML_XINCLUDE_START) || \ ((c_node)->type == XML_XINCLUDE_END)) #define _getNs(c_node) \ (((c_node)->ns == 0) ? 0 : ((c_node)->ns->href)) #include "string.h" static void* lxml_unpack_xmldoc_capsule(PyObject* capsule, int* is_owned) { xmlDoc *c_doc; void *context; *is_owned = 0; if (unlikely_condition(!PyCapsule_IsValid(capsule, (const char*)"libxml2:xmlDoc"))) { PyErr_SetString( PyExc_TypeError, "Not a valid capsule. The capsule argument must be a capsule object with name libxml2:xmlDoc"); return NULL; } c_doc = (xmlDoc*) PyCapsule_GetPointer(capsule, (const char*)"libxml2:xmlDoc"); if (unlikely_condition(!c_doc)) return NULL; if (unlikely_condition(c_doc->type != XML_DOCUMENT_NODE && c_doc->type != XML_HTML_DOCUMENT_NODE)) { PyErr_Format( PyExc_ValueError, "Illegal document provided: expected XML or HTML, found %d", (int)c_doc->type); return NULL; } context = PyCapsule_GetContext(capsule); if (unlikely_condition(!context && PyErr_Occurred())) return NULL; if (context && strcmp((const char*) context, "destructor:xmlFreeDoc") == 0) { /* take ownership by setting destructor to NULL */ if (PyCapsule_SetDestructor(capsule, NULL) == 0) { /* ownership transferred => invalidate capsule by clearing its name */ if (unlikely_condition(PyCapsule_SetName(capsule, NULL))) { /* this should never happen since everything above succeeded */ xmlFreeDoc(c_doc); return NULL; } *is_owned = 1; } } return c_doc; } /* Macro pair implementation of a depth first tree walker * * Calls the code block between the BEGIN and END macros for all elements * below c_tree_top (exclusively), starting at c_node (inclusively iff * 'inclusive' is 1). The _ELEMENT_ variants will only stop on nodes * that match _isElement(), the normal variant will stop on every node * except text nodes. * * To traverse the node and all of its children and siblings in Pyrex, call * cdef xmlNode* some_node * BEGIN_FOR_EACH_ELEMENT_FROM(some_node.parent, some_node, 1) * # do something with some_node * END_FOR_EACH_ELEMENT_FROM(some_node) * * To traverse only the children and siblings of a node, call * cdef xmlNode* some_node * BEGIN_FOR_EACH_ELEMENT_FROM(some_node.parent, some_node, 0) * # do something with some_node * END_FOR_EACH_ELEMENT_FROM(some_node) * * To traverse only the children, do: * cdef xmlNode* some_node * some_node = parent_node.children * BEGIN_FOR_EACH_ELEMENT_FROM(parent_node, some_node, 1) * # do something with some_node * END_FOR_EACH_ELEMENT_FROM(some_node) * * NOTE: 'some_node' MUST be a plain 'xmlNode*' ! * * NOTE: parent modification during the walk can divert the iterator, but * should not segfault ! */ #define _LX__ELEMENT_MATCH(c_node, only_elements) \ ((only_elements) ? (_isElement(c_node)) : 1) #define _LX__ADVANCE_TO_NEXT(c_node, only_elements) \ while ((c_node != 0) && (!_LX__ELEMENT_MATCH(c_node, only_elements))) \ c_node = c_node->next; #define _LX__TRAVERSE_TO_NEXT(c_stop_node, c_node, only_elements) \ { \ /* walk through children first */ \ xmlNode* _lx__next = c_node->children; \ if (_lx__next != 0) { \ if (c_node->type == XML_ENTITY_REF_NODE || c_node->type == XML_DTD_NODE) { \ _lx__next = 0; \ } else { \ _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \ } \ } \ if ((_lx__next == 0) && (c_node != c_stop_node)) { \ /* try siblings */ \ _lx__next = c_node->next; \ _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \ /* back off through parents */ \ while (_lx__next == 0) { \ c_node = c_node->parent; \ if (c_node == 0) \ break; \ if (c_node == c_stop_node) \ break; \ if ((only_elements) && !_isElement(c_node)) \ break; \ /* we already traversed the parents -> siblings */ \ _lx__next = c_node->next; \ _LX__ADVANCE_TO_NEXT(_lx__next, only_elements) \ } \ } \ c_node = _lx__next; \ } #define _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, only_elements) \ { \ if (c_node != 0) { \ const xmlNode* _lx__tree_top = (c_tree_top); \ const int _lx__only_elements = (only_elements); \ /* make sure we start at an element */ \ if (!_LX__ELEMENT_MATCH(c_node, _lx__only_elements)) { \ /* we skip the node, so 'inclusive' is irrelevant */ \ if (c_node == _lx__tree_top) \ c_node = 0; /* nothing to traverse */ \ else { \ c_node = c_node->next; \ _LX__ADVANCE_TO_NEXT(c_node, _lx__only_elements) \ } \ } else if (! (inclusive)) { \ /* skip the first node */ \ _LX__TRAVERSE_TO_NEXT(_lx__tree_top, c_node, _lx__only_elements) \ } \ \ /* now run the user code on the elements we find */ \ while (c_node != 0) { \ /* here goes the code to be run for each element */ #define _LX__END_FOR_EACH_FROM(c_node) \ _LX__TRAVERSE_TO_NEXT(_lx__tree_top, c_node, _lx__only_elements) \ } \ } \ } #define BEGIN_FOR_EACH_ELEMENT_FROM(c_tree_top, c_node, inclusive) \ _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, 1) #define END_FOR_EACH_ELEMENT_FROM(c_node) \ _LX__END_FOR_EACH_FROM(c_node) #define BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive) \ _LX__BEGIN_FOR_EACH_FROM(c_tree_top, c_node, inclusive, 0) #define END_FOR_EACH_FROM(c_node) \ _LX__END_FOR_EACH_FROM(c_node) #endif /* HAS_ETREE_DEFS_H */ PK!Mk͔ xmlerror.pxdnu[ # --- BEGIN: GENERATED CONSTANTS --- # This section is generated by the script 'update-error-constants.py'. cdef extern from "libxml/xmlerror.h": ctypedef enum xmlErrorLevel: XML_ERR_NONE = 0 XML_ERR_WARNING = 1 # A simple warning XML_ERR_ERROR = 2 # A recoverable error XML_ERR_FATAL = 3 # A fatal error ctypedef enum xmlErrorDomain: XML_FROM_NONE = 0 XML_FROM_PARSER = 1 # The XML parser XML_FROM_TREE = 2 # The tree module XML_FROM_NAMESPACE = 3 # The XML Namespace module XML_FROM_DTD = 4 # The XML DTD validation with parser contex XML_FROM_HTML = 5 # The HTML parser XML_FROM_MEMORY = 6 # The memory allocator XML_FROM_OUTPUT = 7 # The serialization code XML_FROM_IO = 8 # The Input/Output stack XML_FROM_FTP = 9 # The FTP module XML_FROM_HTTP = 10 # The HTTP module XML_FROM_XINCLUDE = 11 # The XInclude processing XML_FROM_XPATH = 12 # The XPath module XML_FROM_XPOINTER = 13 # The XPointer module XML_FROM_REGEXP = 14 # The regular expressions module XML_FROM_DATATYPE = 15 # The W3C XML Schemas Datatype module XML_FROM_SCHEMASP = 16 # The W3C XML Schemas parser module XML_FROM_SCHEMASV = 17 # The W3C XML Schemas validation module XML_FROM_RELAXNGP = 18 # The Relax-NG parser module XML_FROM_RELAXNGV = 19 # The Relax-NG validator module XML_FROM_CATALOG = 20 # The Catalog module XML_FROM_C14N = 21 # The Canonicalization module XML_FROM_XSLT = 22 # The XSLT engine from libxslt XML_FROM_VALID = 23 # The XML DTD validation with valid context XML_FROM_CHECK = 24 # The error checking module XML_FROM_WRITER = 25 # The xmlwriter module XML_FROM_MODULE = 26 # The dynamically loaded module modul XML_FROM_I18N = 27 # The module handling character conversion XML_FROM_SCHEMATRONV = 28 # The Schematron validator module XML_FROM_BUFFER = 29 # The buffers module XML_FROM_URI = 30 # The URI module ctypedef enum xmlParserErrors: XML_ERR_OK = 0 XML_ERR_INTERNAL_ERROR = 1 XML_ERR_NO_MEMORY = 2 XML_ERR_DOCUMENT_START = 3 XML_ERR_DOCUMENT_EMPTY = 4 XML_ERR_DOCUMENT_END = 5 XML_ERR_INVALID_HEX_CHARREF = 6 XML_ERR_INVALID_DEC_CHARREF = 7 XML_ERR_INVALID_CHARREF = 8 XML_ERR_INVALID_CHAR = 9 XML_ERR_CHARREF_AT_EOF = 10 XML_ERR_CHARREF_IN_PROLOG = 11 XML_ERR_CHARREF_IN_EPILOG = 12 XML_ERR_CHARREF_IN_DTD = 13 XML_ERR_ENTITYREF_AT_EOF = 14 XML_ERR_ENTITYREF_IN_PROLOG = 15 XML_ERR_ENTITYREF_IN_EPILOG = 16 XML_ERR_ENTITYREF_IN_DTD = 17 XML_ERR_PEREF_AT_EOF = 18 XML_ERR_PEREF_IN_PROLOG = 19 XML_ERR_PEREF_IN_EPILOG = 20 XML_ERR_PEREF_IN_INT_SUBSET = 21 XML_ERR_ENTITYREF_NO_NAME = 22 XML_ERR_ENTITYREF_SEMICOL_MISSING = 23 XML_ERR_PEREF_NO_NAME = 24 XML_ERR_PEREF_SEMICOL_MISSING = 25 XML_ERR_UNDECLARED_ENTITY = 26 XML_WAR_UNDECLARED_ENTITY = 27 XML_ERR_UNPARSED_ENTITY = 28 XML_ERR_ENTITY_IS_EXTERNAL = 29 XML_ERR_ENTITY_IS_PARAMETER = 30 XML_ERR_UNKNOWN_ENCODING = 31 XML_ERR_UNSUPPORTED_ENCODING = 32 XML_ERR_STRING_NOT_STARTED = 33 XML_ERR_STRING_NOT_CLOSED = 34 XML_ERR_NS_DECL_ERROR = 35 XML_ERR_ENTITY_NOT_STARTED = 36 XML_ERR_ENTITY_NOT_FINISHED = 37 XML_ERR_LT_IN_ATTRIBUTE = 38 XML_ERR_ATTRIBUTE_NOT_STARTED = 39 XML_ERR_ATTRIBUTE_NOT_FINISHED = 40 XML_ERR_ATTRIBUTE_WITHOUT_VALUE = 41 XML_ERR_ATTRIBUTE_REDEFINED = 42 XML_ERR_LITERAL_NOT_STARTED = 43 XML_ERR_LITERAL_NOT_FINISHED = 44 XML_ERR_COMMENT_NOT_FINISHED = 45 XML_ERR_PI_NOT_STARTED = 46 XML_ERR_PI_NOT_FINISHED = 47 XML_ERR_NOTATION_NOT_STARTED = 48 XML_ERR_NOTATION_NOT_FINISHED = 49 XML_ERR_ATTLIST_NOT_STARTED = 50 XML_ERR_ATTLIST_NOT_FINISHED = 51 XML_ERR_MIXED_NOT_STARTED = 52 XML_ERR_MIXED_NOT_FINISHED = 53 XML_ERR_ELEMCONTENT_NOT_STARTED = 54 XML_ERR_ELEMCONTENT_NOT_FINISHED = 55 XML_ERR_XMLDECL_NOT_STARTED = 56 XML_ERR_XMLDECL_NOT_FINISHED = 57 XML_ERR_CONDSEC_NOT_STARTED = 58 XML_ERR_CONDSEC_NOT_FINISHED = 59 XML_ERR_EXT_SUBSET_NOT_FINISHED = 60 XML_ERR_DOCTYPE_NOT_FINISHED = 61 XML_ERR_MISPLACED_CDATA_END = 62 XML_ERR_CDATA_NOT_FINISHED = 63 XML_ERR_RESERVED_XML_NAME = 64 XML_ERR_SPACE_REQUIRED = 65 XML_ERR_SEPARATOR_REQUIRED = 66 XML_ERR_NMTOKEN_REQUIRED = 67 XML_ERR_NAME_REQUIRED = 68 XML_ERR_PCDATA_REQUIRED = 69 XML_ERR_URI_REQUIRED = 70 XML_ERR_PUBID_REQUIRED = 71 XML_ERR_LT_REQUIRED = 72 XML_ERR_GT_REQUIRED = 73 XML_ERR_LTSLASH_REQUIRED = 74 XML_ERR_EQUAL_REQUIRED = 75 XML_ERR_TAG_NAME_MISMATCH = 76 XML_ERR_TAG_NOT_FINISHED = 77 XML_ERR_STANDALONE_VALUE = 78 XML_ERR_ENCODING_NAME = 79 XML_ERR_HYPHEN_IN_COMMENT = 80 XML_ERR_INVALID_ENCODING = 81 XML_ERR_EXT_ENTITY_STANDALONE = 82 XML_ERR_CONDSEC_INVALID = 83 XML_ERR_VALUE_REQUIRED = 84 XML_ERR_NOT_WELL_BALANCED = 85 XML_ERR_EXTRA_CONTENT = 86 XML_ERR_ENTITY_CHAR_ERROR = 87 XML_ERR_ENTITY_PE_INTERNAL = 88 XML_ERR_ENTITY_LOOP = 89 XML_ERR_ENTITY_BOUNDARY = 90 XML_ERR_INVALID_URI = 91 XML_ERR_URI_FRAGMENT = 92 XML_WAR_CATALOG_PI = 93 XML_ERR_NO_DTD = 94 XML_ERR_CONDSEC_INVALID_KEYWORD = 95 XML_ERR_VERSION_MISSING = 96 XML_WAR_UNKNOWN_VERSION = 97 XML_WAR_LANG_VALUE = 98 XML_WAR_NS_URI = 99 XML_WAR_NS_URI_RELATIVE = 100 XML_ERR_MISSING_ENCODING = 101 XML_WAR_SPACE_VALUE = 102 XML_ERR_NOT_STANDALONE = 103 XML_ERR_ENTITY_PROCESSING = 104 XML_ERR_NOTATION_PROCESSING = 105 XML_WAR_NS_COLUMN = 106 XML_WAR_ENTITY_REDEFINED = 107 XML_ERR_UNKNOWN_VERSION = 108 XML_ERR_VERSION_MISMATCH = 109 XML_ERR_NAME_TOO_LONG = 110 XML_ERR_USER_STOP = 111 XML_ERR_COMMENT_ABRUPTLY_ENDED = 112 XML_NS_ERR_XML_NAMESPACE = 200 XML_NS_ERR_UNDEFINED_NAMESPACE = 201 XML_NS_ERR_QNAME = 202 XML_NS_ERR_ATTRIBUTE_REDEFINED = 203 XML_NS_ERR_EMPTY = 204 XML_NS_ERR_COLON = 205 XML_DTD_ATTRIBUTE_DEFAULT = 500 XML_DTD_ATTRIBUTE_REDEFINED = 501 XML_DTD_ATTRIBUTE_VALUE = 502 XML_DTD_CONTENT_ERROR = 503 XML_DTD_CONTENT_MODEL = 504 XML_DTD_CONTENT_NOT_DETERMINIST = 505 XML_DTD_DIFFERENT_PREFIX = 506 XML_DTD_ELEM_DEFAULT_NAMESPACE = 507 XML_DTD_ELEM_NAMESPACE = 508 XML_DTD_ELEM_REDEFINED = 509 XML_DTD_EMPTY_NOTATION = 510 XML_DTD_ENTITY_TYPE = 511 XML_DTD_ID_FIXED = 512 XML_DTD_ID_REDEFINED = 513 XML_DTD_ID_SUBSET = 514 XML_DTD_INVALID_CHILD = 515 XML_DTD_INVALID_DEFAULT = 516 XML_DTD_LOAD_ERROR = 517 XML_DTD_MISSING_ATTRIBUTE = 518 XML_DTD_MIXED_CORRUPT = 519 XML_DTD_MULTIPLE_ID = 520 XML_DTD_NO_DOC = 521 XML_DTD_NO_DTD = 522 XML_DTD_NO_ELEM_NAME = 523 XML_DTD_NO_PREFIX = 524 XML_DTD_NO_ROOT = 525 XML_DTD_NOTATION_REDEFINED = 526 XML_DTD_NOTATION_VALUE = 527 XML_DTD_NOT_EMPTY = 528 XML_DTD_NOT_PCDATA = 529 XML_DTD_NOT_STANDALONE = 530 XML_DTD_ROOT_NAME = 531 XML_DTD_STANDALONE_WHITE_SPACE = 532 XML_DTD_UNKNOWN_ATTRIBUTE = 533 XML_DTD_UNKNOWN_ELEM = 534 XML_DTD_UNKNOWN_ENTITY = 535 XML_DTD_UNKNOWN_ID = 536 XML_DTD_UNKNOWN_NOTATION = 537 XML_DTD_STANDALONE_DEFAULTED = 538 XML_DTD_XMLID_VALUE = 539 XML_DTD_XMLID_TYPE = 540 XML_DTD_DUP_TOKEN = 541 XML_HTML_STRUCURE_ERROR = 800 XML_HTML_UNKNOWN_TAG = 801 XML_RNGP_ANYNAME_ATTR_ANCESTOR = 1000 XML_RNGP_ATTR_CONFLICT = 1001 XML_RNGP_ATTRIBUTE_CHILDREN = 1002 XML_RNGP_ATTRIBUTE_CONTENT = 1003 XML_RNGP_ATTRIBUTE_EMPTY = 1004 XML_RNGP_ATTRIBUTE_NOOP = 1005 XML_RNGP_CHOICE_CONTENT = 1006 XML_RNGP_CHOICE_EMPTY = 1007 XML_RNGP_CREATE_FAILURE = 1008 XML_RNGP_DATA_CONTENT = 1009 XML_RNGP_DEF_CHOICE_AND_INTERLEAVE = 1010 XML_RNGP_DEFINE_CREATE_FAILED = 1011 XML_RNGP_DEFINE_EMPTY = 1012 XML_RNGP_DEFINE_MISSING = 1013 XML_RNGP_DEFINE_NAME_MISSING = 1014 XML_RNGP_ELEM_CONTENT_EMPTY = 1015 XML_RNGP_ELEM_CONTENT_ERROR = 1016 XML_RNGP_ELEMENT_EMPTY = 1017 XML_RNGP_ELEMENT_CONTENT = 1018 XML_RNGP_ELEMENT_NAME = 1019 XML_RNGP_ELEMENT_NO_CONTENT = 1020 XML_RNGP_ELEM_TEXT_CONFLICT = 1021 XML_RNGP_EMPTY = 1022 XML_RNGP_EMPTY_CONSTRUCT = 1023 XML_RNGP_EMPTY_CONTENT = 1024 XML_RNGP_EMPTY_NOT_EMPTY = 1025 XML_RNGP_ERROR_TYPE_LIB = 1026 XML_RNGP_EXCEPT_EMPTY = 1027 XML_RNGP_EXCEPT_MISSING = 1028 XML_RNGP_EXCEPT_MULTIPLE = 1029 XML_RNGP_EXCEPT_NO_CONTENT = 1030 XML_RNGP_EXTERNALREF_EMTPY = 1031 XML_RNGP_EXTERNAL_REF_FAILURE = 1032 XML_RNGP_EXTERNALREF_RECURSE = 1033 XML_RNGP_FORBIDDEN_ATTRIBUTE = 1034 XML_RNGP_FOREIGN_ELEMENT = 1035 XML_RNGP_GRAMMAR_CONTENT = 1036 XML_RNGP_GRAMMAR_EMPTY = 1037 XML_RNGP_GRAMMAR_MISSING = 1038 XML_RNGP_GRAMMAR_NO_START = 1039 XML_RNGP_GROUP_ATTR_CONFLICT = 1040 XML_RNGP_HREF_ERROR = 1041 XML_RNGP_INCLUDE_EMPTY = 1042 XML_RNGP_INCLUDE_FAILURE = 1043 XML_RNGP_INCLUDE_RECURSE = 1044 XML_RNGP_INTERLEAVE_ADD = 1045 XML_RNGP_INTERLEAVE_CREATE_FAILED = 1046 XML_RNGP_INTERLEAVE_EMPTY = 1047 XML_RNGP_INTERLEAVE_NO_CONTENT = 1048 XML_RNGP_INVALID_DEFINE_NAME = 1049 XML_RNGP_INVALID_URI = 1050 XML_RNGP_INVALID_VALUE = 1051 XML_RNGP_MISSING_HREF = 1052 XML_RNGP_NAME_MISSING = 1053 XML_RNGP_NEED_COMBINE = 1054 XML_RNGP_NOTALLOWED_NOT_EMPTY = 1055 XML_RNGP_NSNAME_ATTR_ANCESTOR = 1056 XML_RNGP_NSNAME_NO_NS = 1057 XML_RNGP_PARAM_FORBIDDEN = 1058 XML_RNGP_PARAM_NAME_MISSING = 1059 XML_RNGP_PARENTREF_CREATE_FAILED = 1060 XML_RNGP_PARENTREF_NAME_INVALID = 1061 XML_RNGP_PARENTREF_NO_NAME = 1062 XML_RNGP_PARENTREF_NO_PARENT = 1063 XML_RNGP_PARENTREF_NOT_EMPTY = 1064 XML_RNGP_PARSE_ERROR = 1065 XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME = 1066 XML_RNGP_PAT_ATTR_ATTR = 1067 XML_RNGP_PAT_ATTR_ELEM = 1068 XML_RNGP_PAT_DATA_EXCEPT_ATTR = 1069 XML_RNGP_PAT_DATA_EXCEPT_ELEM = 1070 XML_RNGP_PAT_DATA_EXCEPT_EMPTY = 1071 XML_RNGP_PAT_DATA_EXCEPT_GROUP = 1072 XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE = 1073 XML_RNGP_PAT_DATA_EXCEPT_LIST = 1074 XML_RNGP_PAT_DATA_EXCEPT_ONEMORE = 1075 XML_RNGP_PAT_DATA_EXCEPT_REF = 1076 XML_RNGP_PAT_DATA_EXCEPT_TEXT = 1077 XML_RNGP_PAT_LIST_ATTR = 1078 XML_RNGP_PAT_LIST_ELEM = 1079 XML_RNGP_PAT_LIST_INTERLEAVE = 1080 XML_RNGP_PAT_LIST_LIST = 1081 XML_RNGP_PAT_LIST_REF = 1082 XML_RNGP_PAT_LIST_TEXT = 1083 XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME = 1084 XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME = 1085 XML_RNGP_PAT_ONEMORE_GROUP_ATTR = 1086 XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR = 1087 XML_RNGP_PAT_START_ATTR = 1088 XML_RNGP_PAT_START_DATA = 1089 XML_RNGP_PAT_START_EMPTY = 1090 XML_RNGP_PAT_START_GROUP = 1091 XML_RNGP_PAT_START_INTERLEAVE = 1092 XML_RNGP_PAT_START_LIST = 1093 XML_RNGP_PAT_START_ONEMORE = 1094 XML_RNGP_PAT_START_TEXT = 1095 XML_RNGP_PAT_START_VALUE = 1096 XML_RNGP_PREFIX_UNDEFINED = 1097 XML_RNGP_REF_CREATE_FAILED = 1098 XML_RNGP_REF_CYCLE = 1099 XML_RNGP_REF_NAME_INVALID = 1100 XML_RNGP_REF_NO_DEF = 1101 XML_RNGP_REF_NO_NAME = 1102 XML_RNGP_REF_NOT_EMPTY = 1103 XML_RNGP_START_CHOICE_AND_INTERLEAVE = 1104 XML_RNGP_START_CONTENT = 1105 XML_RNGP_START_EMPTY = 1106 XML_RNGP_START_MISSING = 1107 XML_RNGP_TEXT_EXPECTED = 1108 XML_RNGP_TEXT_HAS_CHILD = 1109 XML_RNGP_TYPE_MISSING = 1110 XML_RNGP_TYPE_NOT_FOUND = 1111 XML_RNGP_TYPE_VALUE = 1112 XML_RNGP_UNKNOWN_ATTRIBUTE = 1113 XML_RNGP_UNKNOWN_COMBINE = 1114 XML_RNGP_UNKNOWN_CONSTRUCT = 1115 XML_RNGP_UNKNOWN_TYPE_LIB = 1116 XML_RNGP_URI_FRAGMENT = 1117 XML_RNGP_URI_NOT_ABSOLUTE = 1118 XML_RNGP_VALUE_EMPTY = 1119 XML_RNGP_VALUE_NO_CONTENT = 1120 XML_RNGP_XMLNS_NAME = 1121 XML_RNGP_XML_NS = 1122 XML_XPATH_EXPRESSION_OK = 1200 XML_XPATH_NUMBER_ERROR = 1201 XML_XPATH_UNFINISHED_LITERAL_ERROR = 1202 XML_XPATH_START_LITERAL_ERROR = 1203 XML_XPATH_VARIABLE_REF_ERROR = 1204 XML_XPATH_UNDEF_VARIABLE_ERROR = 1205 XML_XPATH_INVALID_PREDICATE_ERROR = 1206 XML_XPATH_EXPR_ERROR = 1207 XML_XPATH_UNCLOSED_ERROR = 1208 XML_XPATH_UNKNOWN_FUNC_ERROR = 1209 XML_XPATH_INVALID_OPERAND = 1210 XML_XPATH_INVALID_TYPE = 1211 XML_XPATH_INVALID_ARITY = 1212 XML_XPATH_INVALID_CTXT_SIZE = 1213 XML_XPATH_INVALID_CTXT_POSITION = 1214 XML_XPATH_MEMORY_ERROR = 1215 XML_XPTR_SYNTAX_ERROR = 1216 XML_XPTR_RESOURCE_ERROR = 1217 XML_XPTR_SUB_RESOURCE_ERROR = 1218 XML_XPATH_UNDEF_PREFIX_ERROR = 1219 XML_XPATH_ENCODING_ERROR = 1220 XML_XPATH_INVALID_CHAR_ERROR = 1221 XML_TREE_INVALID_HEX = 1300 XML_TREE_INVALID_DEC = 1301 XML_TREE_UNTERMINATED_ENTITY = 1302 XML_TREE_NOT_UTF8 = 1303 XML_SAVE_NOT_UTF8 = 1400 XML_SAVE_CHAR_INVALID = 1401 XML_SAVE_NO_DOCTYPE = 1402 XML_SAVE_UNKNOWN_ENCODING = 1403 XML_REGEXP_COMPILE_ERROR = 1450 XML_IO_UNKNOWN = 1500 XML_IO_EACCES = 1501 XML_IO_EAGAIN = 1502 XML_IO_EBADF = 1503 XML_IO_EBADMSG = 1504 XML_IO_EBUSY = 1505 XML_IO_ECANCELED = 1506 XML_IO_ECHILD = 1507 XML_IO_EDEADLK = 1508 XML_IO_EDOM = 1509 XML_IO_EEXIST = 1510 XML_IO_EFAULT = 1511 XML_IO_EFBIG = 1512 XML_IO_EINPROGRESS = 1513 XML_IO_EINTR = 1514 XML_IO_EINVAL = 1515 XML_IO_EIO = 1516 XML_IO_EISDIR = 1517 XML_IO_EMFILE = 1518 XML_IO_EMLINK = 1519 XML_IO_EMSGSIZE = 1520 XML_IO_ENAMETOOLONG = 1521 XML_IO_ENFILE = 1522 XML_IO_ENODEV = 1523 XML_IO_ENOENT = 1524 XML_IO_ENOEXEC = 1525 XML_IO_ENOLCK = 1526 XML_IO_ENOMEM = 1527 XML_IO_ENOSPC = 1528 XML_IO_ENOSYS = 1529 XML_IO_ENOTDIR = 1530 XML_IO_ENOTEMPTY = 1531 XML_IO_ENOTSUP = 1532 XML_IO_ENOTTY = 1533 XML_IO_ENXIO = 1534 XML_IO_EPERM = 1535 XML_IO_EPIPE = 1536 XML_IO_ERANGE = 1537 XML_IO_EROFS = 1538 XML_IO_ESPIPE = 1539 XML_IO_ESRCH = 1540 XML_IO_ETIMEDOUT = 1541 XML_IO_EXDEV = 1542 XML_IO_NETWORK_ATTEMPT = 1543 XML_IO_ENCODER = 1544 XML_IO_FLUSH = 1545 XML_IO_WRITE = 1546 XML_IO_NO_INPUT = 1547 XML_IO_BUFFER_FULL = 1548 XML_IO_LOAD_ERROR = 1549 XML_IO_ENOTSOCK = 1550 XML_IO_EISCONN = 1551 XML_IO_ECONNREFUSED = 1552 XML_IO_ENETUNREACH = 1553 XML_IO_EADDRINUSE = 1554 XML_IO_EALREADY = 1555 XML_IO_EAFNOSUPPORT = 1556 XML_XINCLUDE_RECURSION = 1600 XML_XINCLUDE_PARSE_VALUE = 1601 XML_XINCLUDE_ENTITY_DEF_MISMATCH = 1602 XML_XINCLUDE_NO_HREF = 1603 XML_XINCLUDE_NO_FALLBACK = 1604 XML_XINCLUDE_HREF_URI = 1605 XML_XINCLUDE_TEXT_FRAGMENT = 1606 XML_XINCLUDE_TEXT_DOCUMENT = 1607 XML_XINCLUDE_INVALID_CHAR = 1608 XML_XINCLUDE_BUILD_FAILED = 1609 XML_XINCLUDE_UNKNOWN_ENCODING = 1610 XML_XINCLUDE_MULTIPLE_ROOT = 1611 XML_XINCLUDE_XPTR_FAILED = 1612 XML_XINCLUDE_XPTR_RESULT = 1613 XML_XINCLUDE_INCLUDE_IN_INCLUDE = 1614 XML_XINCLUDE_FALLBACKS_IN_INCLUDE = 1615 XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE = 1616 XML_XINCLUDE_DEPRECATED_NS = 1617 XML_XINCLUDE_FRAGMENT_ID = 1618 XML_CATALOG_MISSING_ATTR = 1650 XML_CATALOG_ENTRY_BROKEN = 1651 XML_CATALOG_PREFER_VALUE = 1652 XML_CATALOG_NOT_CATALOG = 1653 XML_CATALOG_RECURSION = 1654 XML_SCHEMAP_PREFIX_UNDEFINED = 1700 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE = 1701 XML_SCHEMAP_ATTRGRP_NONAME_NOREF = 1702 XML_SCHEMAP_ATTR_NONAME_NOREF = 1703 XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF = 1704 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE = 1705 XML_SCHEMAP_ELEM_NONAME_NOREF = 1706 XML_SCHEMAP_EXTENSION_NO_BASE = 1707 XML_SCHEMAP_FACET_NO_VALUE = 1708 XML_SCHEMAP_FAILED_BUILD_IMPORT = 1709 XML_SCHEMAP_GROUP_NONAME_NOREF = 1710 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI = 1711 XML_SCHEMAP_IMPORT_REDEFINE_NSNAME = 1712 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI = 1713 XML_SCHEMAP_INVALID_BOOLEAN = 1714 XML_SCHEMAP_INVALID_ENUM = 1715 XML_SCHEMAP_INVALID_FACET = 1716 XML_SCHEMAP_INVALID_FACET_VALUE = 1717 XML_SCHEMAP_INVALID_MAXOCCURS = 1718 XML_SCHEMAP_INVALID_MINOCCURS = 1719 XML_SCHEMAP_INVALID_REF_AND_SUBTYPE = 1720 XML_SCHEMAP_INVALID_WHITE_SPACE = 1721 XML_SCHEMAP_NOATTR_NOREF = 1722 XML_SCHEMAP_NOTATION_NO_NAME = 1723 XML_SCHEMAP_NOTYPE_NOREF = 1724 XML_SCHEMAP_REF_AND_SUBTYPE = 1725 XML_SCHEMAP_RESTRICTION_NONAME_NOREF = 1726 XML_SCHEMAP_SIMPLETYPE_NONAME = 1727 XML_SCHEMAP_TYPE_AND_SUBTYPE = 1728 XML_SCHEMAP_UNKNOWN_ALL_CHILD = 1729 XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD = 1730 XML_SCHEMAP_UNKNOWN_ATTR_CHILD = 1731 XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD = 1732 XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP = 1733 XML_SCHEMAP_UNKNOWN_BASE_TYPE = 1734 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD = 1735 XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD = 1736 XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD = 1737 XML_SCHEMAP_UNKNOWN_ELEM_CHILD = 1738 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD = 1739 XML_SCHEMAP_UNKNOWN_FACET_CHILD = 1740 XML_SCHEMAP_UNKNOWN_FACET_TYPE = 1741 XML_SCHEMAP_UNKNOWN_GROUP_CHILD = 1742 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD = 1743 XML_SCHEMAP_UNKNOWN_LIST_CHILD = 1744 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD = 1745 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD = 1746 XML_SCHEMAP_UNKNOWN_REF = 1747 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD = 1748 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD = 1749 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD = 1750 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD = 1751 XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD = 1752 XML_SCHEMAP_UNKNOWN_TYPE = 1753 XML_SCHEMAP_UNKNOWN_UNION_CHILD = 1754 XML_SCHEMAP_ELEM_DEFAULT_FIXED = 1755 XML_SCHEMAP_REGEXP_INVALID = 1756 XML_SCHEMAP_FAILED_LOAD = 1757 XML_SCHEMAP_NOTHING_TO_PARSE = 1758 XML_SCHEMAP_NOROOT = 1759 XML_SCHEMAP_REDEFINED_GROUP = 1760 XML_SCHEMAP_REDEFINED_TYPE = 1761 XML_SCHEMAP_REDEFINED_ELEMENT = 1762 XML_SCHEMAP_REDEFINED_ATTRGROUP = 1763 XML_SCHEMAP_REDEFINED_ATTR = 1764 XML_SCHEMAP_REDEFINED_NOTATION = 1765 XML_SCHEMAP_FAILED_PARSE = 1766 XML_SCHEMAP_UNKNOWN_PREFIX = 1767 XML_SCHEMAP_DEF_AND_PREFIX = 1768 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD = 1769 XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI = 1770 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI = 1771 XML_SCHEMAP_NOT_SCHEMA = 1772 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE = 1773 XML_SCHEMAP_INVALID_ATTR_USE = 1774 XML_SCHEMAP_RECURSIVE = 1775 XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE = 1776 XML_SCHEMAP_INVALID_ATTR_COMBINATION = 1777 XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION = 1778 XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD = 1779 XML_SCHEMAP_INVALID_ATTR_NAME = 1780 XML_SCHEMAP_REF_AND_CONTENT = 1781 XML_SCHEMAP_CT_PROPS_CORRECT_1 = 1782 XML_SCHEMAP_CT_PROPS_CORRECT_2 = 1783 XML_SCHEMAP_CT_PROPS_CORRECT_3 = 1784 XML_SCHEMAP_CT_PROPS_CORRECT_4 = 1785 XML_SCHEMAP_CT_PROPS_CORRECT_5 = 1786 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 = 1787 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1 = 1788 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2 = 1789 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2 = 1790 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3 = 1791 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER = 1792 XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE = 1793 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE = 1794 XML_SCHEMAP_SRC_IMPORT_3_1 = 1795 XML_SCHEMAP_SRC_IMPORT_3_2 = 1796 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1 = 1797 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2 = 1798 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3 = 1799 XML_SCHEMAP_COS_CT_EXTENDS_1_3 = 1800 XML_SCHEMAV_NOROOT = 1801 XML_SCHEMAV_UNDECLAREDELEM = 1802 XML_SCHEMAV_NOTTOPLEVEL = 1803 XML_SCHEMAV_MISSING = 1804 XML_SCHEMAV_WRONGELEM = 1805 XML_SCHEMAV_NOTYPE = 1806 XML_SCHEMAV_NOROLLBACK = 1807 XML_SCHEMAV_ISABSTRACT = 1808 XML_SCHEMAV_NOTEMPTY = 1809 XML_SCHEMAV_ELEMCONT = 1810 XML_SCHEMAV_HAVEDEFAULT = 1811 XML_SCHEMAV_NOTNILLABLE = 1812 XML_SCHEMAV_EXTRACONTENT = 1813 XML_SCHEMAV_INVALIDATTR = 1814 XML_SCHEMAV_INVALIDELEM = 1815 XML_SCHEMAV_NOTDETERMINIST = 1816 XML_SCHEMAV_CONSTRUCT = 1817 XML_SCHEMAV_INTERNAL = 1818 XML_SCHEMAV_NOTSIMPLE = 1819 XML_SCHEMAV_ATTRUNKNOWN = 1820 XML_SCHEMAV_ATTRINVALID = 1821 XML_SCHEMAV_VALUE = 1822 XML_SCHEMAV_FACET = 1823 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1 = 1824 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2 = 1825 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3 = 1826 XML_SCHEMAV_CVC_TYPE_3_1_1 = 1827 XML_SCHEMAV_CVC_TYPE_3_1_2 = 1828 XML_SCHEMAV_CVC_FACET_VALID = 1829 XML_SCHEMAV_CVC_LENGTH_VALID = 1830 XML_SCHEMAV_CVC_MINLENGTH_VALID = 1831 XML_SCHEMAV_CVC_MAXLENGTH_VALID = 1832 XML_SCHEMAV_CVC_MININCLUSIVE_VALID = 1833 XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID = 1834 XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID = 1835 XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID = 1836 XML_SCHEMAV_CVC_TOTALDIGITS_VALID = 1837 XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID = 1838 XML_SCHEMAV_CVC_PATTERN_VALID = 1839 XML_SCHEMAV_CVC_ENUMERATION_VALID = 1840 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1 = 1841 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2 = 1842 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3 = 1843 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_4 = 1844 XML_SCHEMAV_CVC_ELT_1 = 1845 XML_SCHEMAV_CVC_ELT_2 = 1846 XML_SCHEMAV_CVC_ELT_3_1 = 1847 XML_SCHEMAV_CVC_ELT_3_2_1 = 1848 XML_SCHEMAV_CVC_ELT_3_2_2 = 1849 XML_SCHEMAV_CVC_ELT_4_1 = 1850 XML_SCHEMAV_CVC_ELT_4_2 = 1851 XML_SCHEMAV_CVC_ELT_4_3 = 1852 XML_SCHEMAV_CVC_ELT_5_1_1 = 1853 XML_SCHEMAV_CVC_ELT_5_1_2 = 1854 XML_SCHEMAV_CVC_ELT_5_2_1 = 1855 XML_SCHEMAV_CVC_ELT_5_2_2_1 = 1856 XML_SCHEMAV_CVC_ELT_5_2_2_2_1 = 1857 XML_SCHEMAV_CVC_ELT_5_2_2_2_2 = 1858 XML_SCHEMAV_CVC_ELT_6 = 1859 XML_SCHEMAV_CVC_ELT_7 = 1860 XML_SCHEMAV_CVC_ATTRIBUTE_1 = 1861 XML_SCHEMAV_CVC_ATTRIBUTE_2 = 1862 XML_SCHEMAV_CVC_ATTRIBUTE_3 = 1863 XML_SCHEMAV_CVC_ATTRIBUTE_4 = 1864 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_1 = 1865 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1 = 1866 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2 = 1867 XML_SCHEMAV_CVC_COMPLEX_TYPE_4 = 1868 XML_SCHEMAV_CVC_COMPLEX_TYPE_5_1 = 1869 XML_SCHEMAV_CVC_COMPLEX_TYPE_5_2 = 1870 XML_SCHEMAV_ELEMENT_CONTENT = 1871 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING = 1872 XML_SCHEMAV_CVC_COMPLEX_TYPE_1 = 1873 XML_SCHEMAV_CVC_AU = 1874 XML_SCHEMAV_CVC_TYPE_1 = 1875 XML_SCHEMAV_CVC_TYPE_2 = 1876 XML_SCHEMAV_CVC_IDC = 1877 XML_SCHEMAV_CVC_WILDCARD = 1878 XML_SCHEMAV_MISC = 1879 XML_XPTR_UNKNOWN_SCHEME = 1900 XML_XPTR_CHILDSEQ_START = 1901 XML_XPTR_EVAL_FAILED = 1902 XML_XPTR_EXTRA_OBJECTS = 1903 XML_C14N_CREATE_CTXT = 1950 XML_C14N_REQUIRES_UTF8 = 1951 XML_C14N_CREATE_STACK = 1952 XML_C14N_INVALID_NODE = 1953 XML_C14N_UNKNOW_NODE = 1954 XML_C14N_RELATIVE_NAMESPACE = 1955 XML_FTP_PASV_ANSWER = 2000 XML_FTP_EPSV_ANSWER = 2001 XML_FTP_ACCNT = 2002 XML_FTP_URL_SYNTAX = 2003 XML_HTTP_URL_SYNTAX = 2020 XML_HTTP_USE_IP = 2021 XML_HTTP_UNKNOWN_HOST = 2022 XML_SCHEMAP_SRC_SIMPLE_TYPE_1 = 3000 XML_SCHEMAP_SRC_SIMPLE_TYPE_2 = 3001 XML_SCHEMAP_SRC_SIMPLE_TYPE_3 = 3002 XML_SCHEMAP_SRC_SIMPLE_TYPE_4 = 3003 XML_SCHEMAP_SRC_RESOLVE = 3004 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE = 3005 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE = 3006 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES = 3007 XML_SCHEMAP_ST_PROPS_CORRECT_1 = 3008 XML_SCHEMAP_ST_PROPS_CORRECT_2 = 3009 XML_SCHEMAP_ST_PROPS_CORRECT_3 = 3010 XML_SCHEMAP_COS_ST_RESTRICTS_1_1 = 3011 XML_SCHEMAP_COS_ST_RESTRICTS_1_2 = 3012 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1 = 3013 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_2 = 3014 XML_SCHEMAP_COS_ST_RESTRICTS_2_1 = 3015 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1 = 3016 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2 = 3017 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1 = 3018 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2 = 3019 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3 = 3020 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4 = 3021 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_5 = 3022 XML_SCHEMAP_COS_ST_RESTRICTS_3_1 = 3023 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1 = 3024 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2 = 3025 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2 = 3026 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1 = 3027 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3 = 3028 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4 = 3029 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_5 = 3030 XML_SCHEMAP_COS_ST_DERIVED_OK_2_1 = 3031 XML_SCHEMAP_COS_ST_DERIVED_OK_2_2 = 3032 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED = 3033 XML_SCHEMAP_S4S_ELEM_MISSING = 3034 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED = 3035 XML_SCHEMAP_S4S_ATTR_MISSING = 3036 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE = 3037 XML_SCHEMAP_SRC_ELEMENT_1 = 3038 XML_SCHEMAP_SRC_ELEMENT_2_1 = 3039 XML_SCHEMAP_SRC_ELEMENT_2_2 = 3040 XML_SCHEMAP_SRC_ELEMENT_3 = 3041 XML_SCHEMAP_P_PROPS_CORRECT_1 = 3042 XML_SCHEMAP_P_PROPS_CORRECT_2_1 = 3043 XML_SCHEMAP_P_PROPS_CORRECT_2_2 = 3044 XML_SCHEMAP_E_PROPS_CORRECT_2 = 3045 XML_SCHEMAP_E_PROPS_CORRECT_3 = 3046 XML_SCHEMAP_E_PROPS_CORRECT_4 = 3047 XML_SCHEMAP_E_PROPS_CORRECT_5 = 3048 XML_SCHEMAP_E_PROPS_CORRECT_6 = 3049 XML_SCHEMAP_SRC_INCLUDE = 3050 XML_SCHEMAP_SRC_ATTRIBUTE_1 = 3051 XML_SCHEMAP_SRC_ATTRIBUTE_2 = 3052 XML_SCHEMAP_SRC_ATTRIBUTE_3_1 = 3053 XML_SCHEMAP_SRC_ATTRIBUTE_3_2 = 3054 XML_SCHEMAP_SRC_ATTRIBUTE_4 = 3055 XML_SCHEMAP_NO_XMLNS = 3056 XML_SCHEMAP_NO_XSI = 3057 XML_SCHEMAP_COS_VALID_DEFAULT_1 = 3058 XML_SCHEMAP_COS_VALID_DEFAULT_2_1 = 3059 XML_SCHEMAP_COS_VALID_DEFAULT_2_2_1 = 3060 XML_SCHEMAP_COS_VALID_DEFAULT_2_2_2 = 3061 XML_SCHEMAP_CVC_SIMPLE_TYPE = 3062 XML_SCHEMAP_COS_CT_EXTENDS_1_1 = 3063 XML_SCHEMAP_SRC_IMPORT_1_1 = 3064 XML_SCHEMAP_SRC_IMPORT_1_2 = 3065 XML_SCHEMAP_SRC_IMPORT_2 = 3066 XML_SCHEMAP_SRC_IMPORT_2_1 = 3067 XML_SCHEMAP_SRC_IMPORT_2_2 = 3068 XML_SCHEMAP_INTERNAL = 3069 # 3069 non-W3C XML_SCHEMAP_NOT_DETERMINISTIC = 3070 # 3070 non-W3C XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_1 = 3071 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_2 = 3072 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3 = 3073 XML_SCHEMAP_MG_PROPS_CORRECT_1 = 3074 XML_SCHEMAP_MG_PROPS_CORRECT_2 = 3075 XML_SCHEMAP_SRC_CT_1 = 3076 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3 = 3077 XML_SCHEMAP_AU_PROPS_CORRECT_2 = 3078 XML_SCHEMAP_A_PROPS_CORRECT_2 = 3079 XML_SCHEMAP_C_PROPS_CORRECT = 3080 XML_SCHEMAP_SRC_REDEFINE = 3081 XML_SCHEMAP_SRC_IMPORT = 3082 XML_SCHEMAP_WARN_SKIP_SCHEMA = 3083 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA = 3084 XML_SCHEMAP_WARN_ATTR_REDECL_PROH = 3085 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH = 3086 # 3085 XML_SCHEMAP_AG_PROPS_CORRECT = 3087 # 3086 XML_SCHEMAP_COS_CT_EXTENDS_1_2 = 3088 # 3087 XML_SCHEMAP_AU_PROPS_CORRECT = 3089 # 3088 XML_SCHEMAP_A_PROPS_CORRECT_3 = 3090 # 3089 XML_SCHEMAP_COS_ALL_LIMITED = 3091 # 3090 XML_SCHEMATRONV_ASSERT = 4000 XML_SCHEMATRONV_REPORT = 4001 XML_MODULE_OPEN = 4900 XML_MODULE_CLOSE = 4901 XML_CHECK_FOUND_ELEMENT = 5000 XML_CHECK_FOUND_ATTRIBUTE = 5001 XML_CHECK_FOUND_TEXT = 5002 XML_CHECK_FOUND_CDATA = 5003 XML_CHECK_FOUND_ENTITYREF = 5004 XML_CHECK_FOUND_ENTITY = 5005 XML_CHECK_FOUND_PI = 5006 XML_CHECK_FOUND_COMMENT = 5007 XML_CHECK_FOUND_DOCTYPE = 5008 XML_CHECK_FOUND_FRAGMENT = 5009 XML_CHECK_FOUND_NOTATION = 5010 XML_CHECK_UNKNOWN_NODE = 5011 XML_CHECK_ENTITY_TYPE = 5012 XML_CHECK_NO_PARENT = 5013 XML_CHECK_NO_DOC = 5014 XML_CHECK_NO_NAME = 5015 XML_CHECK_NO_ELEM = 5016 XML_CHECK_WRONG_DOC = 5017 XML_CHECK_NO_PREV = 5018 XML_CHECK_WRONG_PREV = 5019 XML_CHECK_NO_NEXT = 5020 XML_CHECK_WRONG_NEXT = 5021 XML_CHECK_NOT_DTD = 5022 XML_CHECK_NOT_ATTR = 5023 XML_CHECK_NOT_ATTR_DECL = 5024 XML_CHECK_NOT_ELEM_DECL = 5025 XML_CHECK_NOT_ENTITY_DECL = 5026 XML_CHECK_NOT_NS_DECL = 5027 XML_CHECK_NO_HREF = 5028 XML_CHECK_WRONG_PARENT = 5029 XML_CHECK_NS_SCOPE = 5030 XML_CHECK_NS_ANCESTOR = 5031 XML_CHECK_NOT_UTF8 = 5032 XML_CHECK_NO_DICT = 5033 XML_CHECK_NOT_NCNAME = 5034 XML_CHECK_OUTSIDE_DICT = 5035 XML_CHECK_WRONG_NAME = 5036 XML_CHECK_NAME_NOT_NULL = 5037 XML_I18N_NO_NAME = 6000 XML_I18N_NO_HANDLER = 6001 XML_I18N_EXCESS_HANDLER = 6002 XML_I18N_CONV_FAILED = 6003 XML_I18N_NO_OUTPUT = 6004 XML_BUF_OVERFLOW = 7000 ctypedef enum xmlRelaxNGValidErr: XML_RELAXNG_OK = 0 XML_RELAXNG_ERR_MEMORY = 1 XML_RELAXNG_ERR_TYPE = 2 XML_RELAXNG_ERR_TYPEVAL = 3 XML_RELAXNG_ERR_DUPID = 4 XML_RELAXNG_ERR_TYPECMP = 5 XML_RELAXNG_ERR_NOSTATE = 6 XML_RELAXNG_ERR_NODEFINE = 7 XML_RELAXNG_ERR_LISTEXTRA = 8 XML_RELAXNG_ERR_LISTEMPTY = 9 XML_RELAXNG_ERR_INTERNODATA = 10 XML_RELAXNG_ERR_INTERSEQ = 11 XML_RELAXNG_ERR_INTEREXTRA = 12 XML_RELAXNG_ERR_ELEMNAME = 13 XML_RELAXNG_ERR_ATTRNAME = 14 XML_RELAXNG_ERR_ELEMNONS = 15 XML_RELAXNG_ERR_ATTRNONS = 16 XML_RELAXNG_ERR_ELEMWRONGNS = 17 XML_RELAXNG_ERR_ATTRWRONGNS = 18 XML_RELAXNG_ERR_ELEMEXTRANS = 19 XML_RELAXNG_ERR_ATTREXTRANS = 20 XML_RELAXNG_ERR_ELEMNOTEMPTY = 21 XML_RELAXNG_ERR_NOELEM = 22 XML_RELAXNG_ERR_NOTELEM = 23 XML_RELAXNG_ERR_ATTRVALID = 24 XML_RELAXNG_ERR_CONTENTVALID = 25 XML_RELAXNG_ERR_EXTRACONTENT = 26 XML_RELAXNG_ERR_INVALIDATTR = 27 XML_RELAXNG_ERR_DATAELEM = 28 XML_RELAXNG_ERR_VALELEM = 29 XML_RELAXNG_ERR_LISTELEM = 30 XML_RELAXNG_ERR_DATATYPE = 31 XML_RELAXNG_ERR_VALUE = 32 XML_RELAXNG_ERR_LIST = 33 XML_RELAXNG_ERR_NOGRAMMAR = 34 XML_RELAXNG_ERR_EXTRADATA = 35 XML_RELAXNG_ERR_LACKDATA = 36 XML_RELAXNG_ERR_INTERNAL = 37 XML_RELAXNG_ERR_ELEMWRONG = 38 XML_RELAXNG_ERR_TEXTWRONG = 39 # --- END: GENERATED CONSTANTS --- cdef extern from "libxml/xmlerror.h": ctypedef struct xmlError: int domain int code char* message xmlErrorLevel level char* file char* str1 char* str2 char* str3 int line int int1 int int2 void* node ctypedef void (*xmlGenericErrorFunc)(void* ctxt, char* msg, ...) nogil ctypedef void (*xmlStructuredErrorFunc)(void* userData, xmlError* error) nogil cdef void xmlSetGenericErrorFunc( void* ctxt, xmlGenericErrorFunc func) nogil cdef void xmlSetStructuredErrorFunc( void* ctxt, xmlStructuredErrorFunc func) nogil cdef extern from "libxml/globals.h": cdef xmlStructuredErrorFunc xmlStructuredError cdef void* xmlStructuredErrorContext PK! __init__.pxdnu[PK!,Tm m relaxng.pxdnu[from lxml.includes.tree cimport xmlDoc from lxml.includes.xmlerror cimport xmlStructuredErrorFunc cdef extern from "libxml/relaxng.h": ctypedef struct xmlRelaxNG ctypedef struct xmlRelaxNGParserCtxt ctypedef struct xmlRelaxNGValidCtxt ctypedef enum xmlRelaxNGValidErr: XML_RELAXNG_OK = 0 XML_RELAXNG_ERR_MEMORY = 1 XML_RELAXNG_ERR_TYPE = 2 XML_RELAXNG_ERR_TYPEVAL = 3 XML_RELAXNG_ERR_DUPID = 4 XML_RELAXNG_ERR_TYPECMP = 5 XML_RELAXNG_ERR_NOSTATE = 6 XML_RELAXNG_ERR_NODEFINE = 7 XML_RELAXNG_ERR_LISTEXTRA = 8 XML_RELAXNG_ERR_LISTEMPTY = 9 XML_RELAXNG_ERR_INTERNODATA = 10 XML_RELAXNG_ERR_INTERSEQ = 11 XML_RELAXNG_ERR_INTEREXTRA = 12 XML_RELAXNG_ERR_ELEMNAME = 13 XML_RELAXNG_ERR_ATTRNAME = 14 XML_RELAXNG_ERR_ELEMNONS = 15 XML_RELAXNG_ERR_ATTRNONS = 16 XML_RELAXNG_ERR_ELEMWRONGNS = 17 XML_RELAXNG_ERR_ATTRWRONGNS = 18 XML_RELAXNG_ERR_ELEMEXTRANS = 19 XML_RELAXNG_ERR_ATTREXTRANS = 20 XML_RELAXNG_ERR_ELEMNOTEMPTY = 21 XML_RELAXNG_ERR_NOELEM = 22 XML_RELAXNG_ERR_NOTELEM = 23 XML_RELAXNG_ERR_ATTRVALID = 24 XML_RELAXNG_ERR_CONTENTVALID = 25 XML_RELAXNG_ERR_EXTRACONTENT = 26 XML_RELAXNG_ERR_INVALIDATTR = 27 XML_RELAXNG_ERR_DATAELEM = 28 XML_RELAXNG_ERR_VALELEM = 29 XML_RELAXNG_ERR_LISTELEM = 30 XML_RELAXNG_ERR_DATATYPE = 31 XML_RELAXNG_ERR_VALUE = 32 XML_RELAXNG_ERR_LIST = 33 XML_RELAXNG_ERR_NOGRAMMAR = 34 XML_RELAXNG_ERR_EXTRADATA = 35 XML_RELAXNG_ERR_LACKDATA = 36 XML_RELAXNG_ERR_INTERNAL = 37 XML_RELAXNG_ERR_ELEMWRONG = 38 XML_RELAXNG_ERR_TEXTWRONG = 39 cdef xmlRelaxNGValidCtxt* xmlRelaxNGNewValidCtxt(xmlRelaxNG* schema) nogil cdef int xmlRelaxNGValidateDoc(xmlRelaxNGValidCtxt* ctxt, xmlDoc* doc) nogil cdef xmlRelaxNG* xmlRelaxNGParse(xmlRelaxNGParserCtxt* ctxt) nogil cdef xmlRelaxNGParserCtxt* xmlRelaxNGNewParserCtxt(char* URL) nogil cdef xmlRelaxNGParserCtxt* xmlRelaxNGNewDocParserCtxt(xmlDoc* doc) nogil cdef void xmlRelaxNGFree(xmlRelaxNG* schema) nogil cdef void xmlRelaxNGFreeParserCtxt(xmlRelaxNGParserCtxt* ctxt) nogil cdef void xmlRelaxNGFreeValidCtxt(xmlRelaxNGValidCtxt* ctxt) nogil cdef void xmlRelaxNGSetValidStructuredErrors( xmlRelaxNGValidCtxt* ctxt, xmlStructuredErrorFunc serror, void *ctx) nogil cdef void xmlRelaxNGSetParserStructuredErrors( xmlRelaxNGParserCtxt* ctxt, xmlStructuredErrorFunc serror, void *ctx) nogil PK!" xslt.pxdnu[from lxml.includes.tree cimport xmlDoc, xmlNode, xmlDict, xmlChar, const_xmlChar, xmlOutputBuffer from lxml.includes.xmlerror cimport xmlGenericErrorFunc from lxml.includes.xpath cimport xmlXPathContext, xmlXPathFunction from libc.string cimport const_char cdef extern from "libxslt/xslt.h": cdef int xsltLibxsltVersion cdef int xsltMaxDepth cdef extern from "libxslt/xsltconfig.h": cdef int LIBXSLT_VERSION cdef extern from "libxslt/xsltInternals.h": ctypedef enum xsltTransformState: XSLT_STATE_OK # 0 XSLT_STATE_ERROR # 1 XSLT_STATE_STOPPED # 2 ctypedef struct xsltDocument: xmlDoc* doc ctypedef struct xsltStylesheet: xmlChar* encoding xmlDoc* doc int errors ctypedef struct xsltTransformContext: xsltStylesheet* style xmlXPathContext* xpathCtxt xsltDocument* document void* _private xmlDict* dict int profile xmlNode* node xmlDoc* output xmlNode* insert xmlNode* inst xsltTransformState state ctypedef struct xsltStackElem ctypedef struct xsltTemplate cdef xsltStylesheet* xsltParseStylesheetDoc(xmlDoc* doc) nogil cdef void xsltFreeStylesheet(xsltStylesheet* sheet) nogil cdef extern from "libxslt/imports.h": # actually defined in "etree_defs.h" cdef void LXML_GET_XSLT_ENCODING(const_xmlChar* result_var, xsltStylesheet* style) cdef extern from "libxslt/extensions.h": ctypedef void (*xsltTransformFunction)(xsltTransformContext* ctxt, xmlNode* context_node, xmlNode* inst, void* precomp_unused) nogil cdef int xsltRegisterExtFunction(xsltTransformContext* ctxt, const_xmlChar* name, const_xmlChar* URI, xmlXPathFunction function) nogil cdef int xsltRegisterExtModuleFunction(const_xmlChar* name, const_xmlChar* URI, xmlXPathFunction function) nogil cdef int xsltUnregisterExtModuleFunction(const_xmlChar* name, const_xmlChar* URI) cdef xmlXPathFunction xsltExtModuleFunctionLookup( const_xmlChar* name, const_xmlChar* URI) nogil cdef int xsltRegisterExtPrefix(xsltStylesheet* style, const_xmlChar* prefix, const_xmlChar* URI) nogil cdef int xsltRegisterExtElement(xsltTransformContext* ctxt, const_xmlChar* name, const_xmlChar* URI, xsltTransformFunction function) nogil cdef extern from "libxslt/documents.h": ctypedef enum xsltLoadType: XSLT_LOAD_START XSLT_LOAD_STYLESHEET XSLT_LOAD_DOCUMENT ctypedef xmlDoc* (*xsltDocLoaderFunc)(const_xmlChar* URI, xmlDict* dict, int options, void* ctxt, xsltLoadType type) nogil cdef xsltDocLoaderFunc xsltDocDefaultLoader cdef void xsltSetLoaderFunc(xsltDocLoaderFunc f) nogil cdef extern from "libxslt/transform.h": cdef xmlDoc* xsltApplyStylesheet(xsltStylesheet* style, xmlDoc* doc, const_char** params) nogil cdef xmlDoc* xsltApplyStylesheetUser(xsltStylesheet* style, xmlDoc* doc, const_char** params, const_char* output, void* profile, xsltTransformContext* context) nogil cdef void xsltProcessOneNode(xsltTransformContext* ctxt, xmlNode* contextNode, xsltStackElem* params) nogil cdef xsltTransformContext* xsltNewTransformContext(xsltStylesheet* style, xmlDoc* doc) nogil cdef void xsltFreeTransformContext(xsltTransformContext* context) nogil cdef void xsltApplyOneTemplate(xsltTransformContext* ctxt, xmlNode* contextNode, xmlNode* list, xsltTemplate* templ, xsltStackElem* params) nogil cdef extern from "libxslt/xsltutils.h": cdef int xsltSaveResultToString(xmlChar** doc_txt_ptr, int* doc_txt_len, xmlDoc* result, xsltStylesheet* style) nogil cdef int xsltSaveResultToFilename(const_char *URL, xmlDoc* result, xsltStylesheet* style, int compression) nogil cdef int xsltSaveResultTo(xmlOutputBuffer* buf, xmlDoc* result, xsltStylesheet* style) nogil cdef xmlGenericErrorFunc xsltGenericError cdef void *xsltGenericErrorContext cdef void xsltSetGenericErrorFunc( void* ctxt, void (*handler)(void* ctxt, char* msg, ...)) nogil cdef void xsltSetTransformErrorFunc( xsltTransformContext*, void* ctxt, void (*handler)(void* ctxt, char* msg, ...) nogil) nogil cdef void xsltTransformError(xsltTransformContext* ctxt, xsltStylesheet* style, xmlNode* node, char* msg, ...) cdef void xsltSetCtxtParseOptions( xsltTransformContext* ctxt, int options) cdef extern from "libxslt/security.h": ctypedef struct xsltSecurityPrefs ctypedef enum xsltSecurityOption: XSLT_SECPREF_READ_FILE = 1 XSLT_SECPREF_WRITE_FILE = 2 XSLT_SECPREF_CREATE_DIRECTORY = 3 XSLT_SECPREF_READ_NETWORK = 4 XSLT_SECPREF_WRITE_NETWORK = 5 ctypedef int (*xsltSecurityCheck)(xsltSecurityPrefs* sec, xsltTransformContext* ctxt, char* value) nogil cdef xsltSecurityPrefs* xsltNewSecurityPrefs() nogil cdef void xsltFreeSecurityPrefs(xsltSecurityPrefs* sec) nogil cdef int xsltSecurityForbid(xsltSecurityPrefs* sec, xsltTransformContext* ctxt, char* value) nogil cdef int xsltSecurityAllow(xsltSecurityPrefs* sec, xsltTransformContext* ctxt, char* value) nogil cdef int xsltSetSecurityPrefs(xsltSecurityPrefs* sec, xsltSecurityOption option, xsltSecurityCheck func) nogil cdef xsltSecurityCheck xsltGetSecurityPrefs( xsltSecurityPrefs* sec, xsltSecurityOption option) nogil cdef int xsltSetCtxtSecurityPrefs(xsltSecurityPrefs* sec, xsltTransformContext* ctxt) nogil cdef xmlDoc* xsltGetProfileInformation(xsltTransformContext* ctxt) nogil cdef extern from "libxslt/variables.h": cdef int xsltQuoteUserParams(xsltTransformContext* ctxt, const_char** params) cdef int xsltQuoteOneUserParam(xsltTransformContext* ctxt, const_xmlChar* name, const_xmlChar* value) cdef extern from "libxslt/extra.h": const_xmlChar* XSLT_LIBXSLT_NAMESPACE const_xmlChar* XSLT_XALAN_NAMESPACE const_xmlChar* XSLT_SAXON_NAMESPACE const_xmlChar* XSLT_XT_NAMESPACE cdef xmlXPathFunction xsltFunctionNodeSet cdef void xsltRegisterAllExtras() nogil cdef extern from "libexslt/exslt.h": cdef void exsltRegisterAll() nogil # libexslt 1.1.25+ const_xmlChar* EXSLT_DATE_NAMESPACE const_xmlChar* EXSLT_SETS_NAMESPACE const_xmlChar* EXSLT_MATH_NAMESPACE const_xmlChar* EXSLT_STRINGS_NAMESPACE cdef int exsltDateXpathCtxtRegister(xmlXPathContext* ctxt, const_xmlChar* prefix) cdef int exsltSetsXpathCtxtRegister(xmlXPathContext* ctxt, const_xmlChar* prefix) cdef int exsltMathXpathCtxtRegister(xmlXPathContext* ctxt, const_xmlChar* prefix) cdef int exsltStrXpathCtxtRegister(xmlXPathContext* ctxt, const_xmlChar* prefix) PK!#e e libxslt/variables.hnu[/* * Summary: interface for the variable matching and lookup. * Description: interface for the variable matching and lookup. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_VARIABLES_H__ #define __XML_XSLT_VARIABLES_H__ #include #include #include "xsltexports.h" #include "xsltInternals.h" #include "functions.h" #ifdef __cplusplus extern "C" { #endif /** * XSLT_REGISTER_VARIABLE_LOOKUP: * * Registering macro, not general purpose at all but used in different modules. */ #define XSLT_REGISTER_VARIABLE_LOOKUP(ctxt) \ xmlXPathRegisterVariableLookup((ctxt)->xpathCtxt, \ xsltXPathVariableLookup, (void *)(ctxt)); \ xsltRegisterAllFunctions((ctxt)->xpathCtxt); \ xsltRegisterAllElement(ctxt); \ (ctxt)->xpathCtxt->extra = ctxt /* * Flags for memory management of RVTs */ /** * XSLT_RVT_LOCAL: * * RVT is destroyed after the current instructions ends. */ #define XSLT_RVT_LOCAL ((void *)1) /** * XSLT_RVT_FUNC_RESULT: * * RVT is part of results returned with func:result. The RVT won't be * destroyed after exiting a template and will be reset to XSLT_RVT_LOCAL or * XSLT_RVT_VARIABLE in the template that receives the return value. */ #define XSLT_RVT_FUNC_RESULT ((void *)2) /** * XSLT_RVT_GLOBAL: * * RVT is part of a global variable. */ #define XSLT_RVT_GLOBAL ((void *)3) /* * Interfaces for the variable module. */ XSLTPUBFUN int XSLTCALL xsltEvalGlobalVariables (xsltTransformContextPtr ctxt); XSLTPUBFUN int XSLTCALL xsltEvalUserParams (xsltTransformContextPtr ctxt, const char **params); XSLTPUBFUN int XSLTCALL xsltQuoteUserParams (xsltTransformContextPtr ctxt, const char **params); XSLTPUBFUN int XSLTCALL xsltEvalOneUserParam (xsltTransformContextPtr ctxt, const xmlChar * name, const xmlChar * value); XSLTPUBFUN int XSLTCALL xsltQuoteOneUserParam (xsltTransformContextPtr ctxt, const xmlChar * name, const xmlChar * value); XSLTPUBFUN void XSLTCALL xsltParseGlobalVariable (xsltStylesheetPtr style, xmlNodePtr cur); XSLTPUBFUN void XSLTCALL xsltParseGlobalParam (xsltStylesheetPtr style, xmlNodePtr cur); XSLTPUBFUN void XSLTCALL xsltParseStylesheetVariable (xsltTransformContextPtr ctxt, xmlNodePtr cur); XSLTPUBFUN void XSLTCALL xsltParseStylesheetParam (xsltTransformContextPtr ctxt, xmlNodePtr cur); XSLTPUBFUN xsltStackElemPtr XSLTCALL xsltParseStylesheetCallerParam (xsltTransformContextPtr ctxt, xmlNodePtr cur); XSLTPUBFUN int XSLTCALL xsltAddStackElemList (xsltTransformContextPtr ctxt, xsltStackElemPtr elems); XSLTPUBFUN void XSLTCALL xsltFreeGlobalVariables (xsltTransformContextPtr ctxt); XSLTPUBFUN xmlXPathObjectPtr XSLTCALL xsltVariableLookup (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri); XSLTPUBFUN xmlXPathObjectPtr XSLTCALL xsltXPathVariableLookup (void *ctxt, const xmlChar *name, const xmlChar *ns_uri); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_VARIABLES_H__ */ PK!r/ libxslt/documents.hnu[/* * Summary: interface for the document handling * Description: implements document loading and cache (multiple * document() reference for the same resources must * be equal. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_DOCUMENTS_H__ #define __XML_XSLT_DOCUMENTS_H__ #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif XSLTPUBFUN xsltDocumentPtr XSLTCALL xsltNewDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc); XSLTPUBFUN xsltDocumentPtr XSLTCALL xsltLoadDocument (xsltTransformContextPtr ctxt, const xmlChar *URI); XSLTPUBFUN xsltDocumentPtr XSLTCALL xsltFindDocument (xsltTransformContextPtr ctxt, xmlDocPtr doc); XSLTPUBFUN void XSLTCALL xsltFreeDocuments (xsltTransformContextPtr ctxt); XSLTPUBFUN xsltDocumentPtr XSLTCALL xsltLoadStyleDocument (xsltStylesheetPtr style, const xmlChar *URI); XSLTPUBFUN xsltDocumentPtr XSLTCALL xsltNewStyleDocument (xsltStylesheetPtr style, xmlDocPtr doc); XSLTPUBFUN void XSLTCALL xsltFreeStyleDocuments (xsltStylesheetPtr style); /* * Hooks for document loading */ /** * xsltLoadType: * * Enum defining the kind of loader requirement. */ typedef enum { XSLT_LOAD_START = 0, /* loading for a top stylesheet */ XSLT_LOAD_STYLESHEET = 1, /* loading for a stylesheet include/import */ XSLT_LOAD_DOCUMENT = 2 /* loading document at transformation time */ } xsltLoadType; /** * xsltDocLoaderFunc: * @URI: the URI of the document to load * @dict: the dictionary to use when parsing that document * @options: parsing options, a set of xmlParserOption * @ctxt: the context, either a stylesheet or a transformation context * @type: the xsltLoadType indicating the kind of loading required * * An xsltDocLoaderFunc is a signature for a function which can be * registered to load document not provided by the compilation or * transformation API themselve, for example when an xsl:import, * xsl:include is found at compilation time or when a document() * call is made at runtime. * * Returns the pointer to the document (which will be modified and * freed by the engine later), or NULL in case of error. */ typedef xmlDocPtr (*xsltDocLoaderFunc) (const xmlChar *URI, xmlDictPtr dict, int options, void *ctxt, xsltLoadType type); XSLTPUBFUN void XSLTCALL xsltSetLoaderFunc (xsltDocLoaderFunc f); /* the loader may be needed by extension libraries so it is exported */ XSLTPUBVAR xsltDocLoaderFunc xsltDocDefaultLoader; #ifdef __cplusplus } #endif #endif /* __XML_XSLT_DOCUMENTS_H__ */ PK!libxslt/xsltInternals.hnu[/* * Summary: internal data structures, constants and functions * Description: Internal data structures, constants and functions used * by the XSLT engine. * They are not part of the API or ABI, i.e. they can change * without prior notice, use carefully. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_INTERNALS_H__ #define __XML_XSLT_INTERNALS_H__ #include #include #include #include #include #include #include #include "xsltexports.h" #include "xsltlocale.h" #include "numbersInternals.h" #ifdef __cplusplus extern "C" { #endif /* #define XSLT_DEBUG_PROFILE_CACHE */ /** * XSLT_IS_TEXT_NODE: * * check if the argument is a text node */ #define XSLT_IS_TEXT_NODE(n) ((n != NULL) && \ (((n)->type == XML_TEXT_NODE) || \ ((n)->type == XML_CDATA_SECTION_NODE))) /** * XSLT_MARK_RES_TREE_FRAG: * * internal macro to set up tree fragments */ #define XSLT_MARK_RES_TREE_FRAG(n) \ (n)->name = (char *) xmlStrdup(BAD_CAST " fake node libxslt"); /** * XSLT_IS_RES_TREE_FRAG: * * internal macro to test tree fragments */ #define XSLT_IS_RES_TREE_FRAG(n) \ ((n != NULL) && ((n)->type == XML_DOCUMENT_NODE) && \ ((n)->name != NULL) && ((n)->name[0] == ' ')) /** * XSLT_REFACTORED_KEYCOMP: * * Internal define to enable on-demand xsl:key computation. * That's the only mode now but the define is kept for compatibility */ #define XSLT_REFACTORED_KEYCOMP /** * XSLT_FAST_IF: * * Internal define to enable usage of xmlXPathCompiledEvalToBoolean() * for XSLT "tests"; e.g. in */ #define XSLT_FAST_IF /** * XSLT_REFACTORED: * * Internal define to enable the refactored parts of Libxslt. */ /* #define XSLT_REFACTORED */ /* ==================================================================== */ /** * XSLT_REFACTORED_VARS: * * Internal define to enable the refactored variable part of libxslt */ #define XSLT_REFACTORED_VARS #ifdef XSLT_REFACTORED extern const xmlChar *xsltXSLTAttrMarker; /* TODO: REMOVE: #define XSLT_REFACTORED_EXCLRESNS */ /* TODO: REMOVE: #define XSLT_REFACTORED_NSALIAS */ /** * XSLT_REFACTORED_XSLT_NSCOMP * * Internal define to enable the pointer-comparison of * namespaces of XSLT elements. */ /* #define XSLT_REFACTORED_XSLT_NSCOMP */ #ifdef XSLT_REFACTORED_XSLT_NSCOMP extern const xmlChar *xsltConstNamespaceNameXSLT; /** * IS_XSLT_ELEM_FAST: * * quick test to detect XSLT elements */ #define IS_XSLT_ELEM_FAST(n) \ (((n) != NULL) && ((n)->ns != NULL) && \ ((n)->ns->href == xsltConstNamespaceNameXSLT)) /** * IS_XSLT_ATTR_FAST: * * quick test to detect XSLT attributes */ #define IS_XSLT_ATTR_FAST(a) \ (((a) != NULL) && ((a)->ns != NULL) && \ ((a)->ns->href == xsltConstNamespaceNameXSLT)) /** * XSLT_HAS_INTERNAL_NSMAP: * * check for namespace mapping */ #define XSLT_HAS_INTERNAL_NSMAP(s) \ (((s) != NULL) && ((s)->principal) && \ ((s)->principal->principalData) && \ ((s)->principal->principalData->nsMap)) /** * XSLT_GET_INTERNAL_NSMAP: * * get pointer to namespace map */ #define XSLT_GET_INTERNAL_NSMAP(s) ((s)->principal->principalData->nsMap) #else /* XSLT_REFACTORED_XSLT_NSCOMP */ /** * IS_XSLT_ELEM_FAST: * * quick check whether this is an xslt element */ #define IS_XSLT_ELEM_FAST(n) \ (((n) != NULL) && ((n)->ns != NULL) && \ (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE))) /** * IS_XSLT_ATTR_FAST: * * quick check for xslt namespace attribute */ #define IS_XSLT_ATTR_FAST(a) \ (((a) != NULL) && ((a)->ns != NULL) && \ (xmlStrEqual((a)->ns->href, XSLT_NAMESPACE))) #endif /* XSLT_REFACTORED_XSLT_NSCOMP */ /** * XSLT_REFACTORED_MANDATORY_VERSION: * * TODO: Currently disabled to surpress regression test failures, since * the old behaviour was that a missing version attribute * produced a only a warning and not an error, which was incerrect. * So the regression tests need to be fixed if this is enabled. */ /* #define XSLT_REFACTORED_MANDATORY_VERSION */ /** * xsltPointerList: * * Pointer-list for various purposes. */ typedef struct _xsltPointerList xsltPointerList; typedef xsltPointerList *xsltPointerListPtr; struct _xsltPointerList { void **items; int number; int size; }; #endif /** * XSLT_REFACTORED_PARSING: * * Internal define to enable the refactored parts of Libxslt * related to parsing. */ /* #define XSLT_REFACTORED_PARSING */ /** * XSLT_MAX_SORT: * * Max number of specified xsl:sort on an element. */ #define XSLT_MAX_SORT 15 /** * XSLT_PAT_NO_PRIORITY: * * Specific value for pattern without priority expressed. */ #define XSLT_PAT_NO_PRIORITY -12345789 /** * xsltRuntimeExtra: * * Extra information added to the transformation context. */ typedef struct _xsltRuntimeExtra xsltRuntimeExtra; typedef xsltRuntimeExtra *xsltRuntimeExtraPtr; struct _xsltRuntimeExtra { void *info; /* pointer to the extra data */ xmlFreeFunc deallocate; /* pointer to the deallocation routine */ union { /* dual-purpose field */ void *ptr; /* data not needing deallocation */ int ival; /* integer value storage */ } val; }; /** * XSLT_RUNTIME_EXTRA_LST: * @ctxt: the transformation context * @nr: the index * * Macro used to access extra information stored in the context */ #define XSLT_RUNTIME_EXTRA_LST(ctxt, nr) (ctxt)->extras[(nr)].info /** * XSLT_RUNTIME_EXTRA_FREE: * @ctxt: the transformation context * @nr: the index * * Macro used to free extra information stored in the context */ #define XSLT_RUNTIME_EXTRA_FREE(ctxt, nr) (ctxt)->extras[(nr)].deallocate /** * XSLT_RUNTIME_EXTRA: * @ctxt: the transformation context * @nr: the index * * Macro used to define extra information stored in the context */ #define XSLT_RUNTIME_EXTRA(ctxt, nr, typ) (ctxt)->extras[(nr)].val.typ /** * xsltTemplate: * * The in-memory structure corresponding to an XSLT Template. */ typedef struct _xsltTemplate xsltTemplate; typedef xsltTemplate *xsltTemplatePtr; struct _xsltTemplate { struct _xsltTemplate *next;/* chained list sorted by priority */ struct _xsltStylesheet *style;/* the containing stylesheet */ xmlChar *match; /* the matching string */ float priority; /* as given from the stylesheet, not computed */ const xmlChar *name; /* the local part of the name QName */ const xmlChar *nameURI; /* the URI part of the name QName */ const xmlChar *mode;/* the local part of the mode QName */ const xmlChar *modeURI;/* the URI part of the mode QName */ xmlNodePtr content; /* the template replacement value */ xmlNodePtr elem; /* the source element */ /* * TODO: @inheritedNsNr and @inheritedNs won't be used in the * refactored code. */ int inheritedNsNr; /* number of inherited namespaces */ xmlNsPtr *inheritedNs;/* inherited non-excluded namespaces */ /* Profiling information */ int nbCalls; /* the number of time the template was called */ unsigned long time; /* the time spent in this template */ void *params; /* xsl:param instructions */ int templNr; /* Nb of templates in the stack */ int templMax; /* Size of the templtes stack */ xsltTemplatePtr *templCalledTab; /* templates called */ int *templCountTab; /* .. and how often */ /* Conflict resolution */ int position; }; /** * xsltDecimalFormat: * * Data structure of decimal-format. */ typedef struct _xsltDecimalFormat xsltDecimalFormat; typedef xsltDecimalFormat *xsltDecimalFormatPtr; struct _xsltDecimalFormat { struct _xsltDecimalFormat *next; /* chained list */ xmlChar *name; /* Used for interpretation of pattern */ xmlChar *digit; xmlChar *patternSeparator; /* May appear in result */ xmlChar *minusSign; xmlChar *infinity; xmlChar *noNumber; /* Not-a-number */ /* Used for interpretation of pattern and may appear in result */ xmlChar *decimalPoint; xmlChar *grouping; xmlChar *percent; xmlChar *permille; xmlChar *zeroDigit; const xmlChar *nsUri; }; /** * xsltDocument: * * Data structure associated to a parsed document. */ typedef struct _xsltDocument xsltDocument; typedef xsltDocument *xsltDocumentPtr; struct _xsltDocument { struct _xsltDocument *next; /* documents are kept in a chained list */ int main; /* is this the main document */ xmlDocPtr doc; /* the parsed document */ void *keys; /* key tables storage */ struct _xsltDocument *includes; /* subsidiary includes */ int preproc; /* pre-processing already done */ int nbKeysComputed; }; /** * xsltKeyDef: * * Representation of an xsl:key. */ typedef struct _xsltKeyDef xsltKeyDef; typedef xsltKeyDef *xsltKeyDefPtr; struct _xsltKeyDef { struct _xsltKeyDef *next; xmlNodePtr inst; xmlChar *name; xmlChar *nameURI; xmlChar *match; xmlChar *use; xmlXPathCompExprPtr comp; xmlXPathCompExprPtr usecomp; xmlNsPtr *nsList; /* the namespaces in scope */ int nsNr; /* the number of namespaces in scope */ }; /** * xsltKeyTable: * * Holds the computed keys for key definitions of the same QName. * Is owned by an xsltDocument. */ typedef struct _xsltKeyTable xsltKeyTable; typedef xsltKeyTable *xsltKeyTablePtr; struct _xsltKeyTable { struct _xsltKeyTable *next; xmlChar *name; xmlChar *nameURI; xmlHashTablePtr keys; }; /* * The in-memory structure corresponding to an XSLT Stylesheet. * NOTE: most of the content is simply linked from the doc tree * structure, no specific allocation is made. */ typedef struct _xsltStylesheet xsltStylesheet; typedef xsltStylesheet *xsltStylesheetPtr; typedef struct _xsltTransformContext xsltTransformContext; typedef xsltTransformContext *xsltTransformContextPtr; /** * xsltElemPreComp: * * The in-memory structure corresponding to element precomputed data, * designed to be extended by extension implementors. */ typedef struct _xsltElemPreComp xsltElemPreComp; typedef xsltElemPreComp *xsltElemPreCompPtr; /** * xsltTransformFunction: * @ctxt: the XSLT transformation context * @node: the input node * @inst: the stylesheet node * @comp: the compiled information from the stylesheet * * Signature of the function associated to elements part of the * stylesheet language like xsl:if or xsl:apply-templates. */ typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); /** * xsltSortFunc: * @ctxt: a transformation context * @sorts: the node-set to sort * @nbsorts: the number of sorts * * Signature of the function to use during sorting */ typedef void (*xsltSortFunc) (xsltTransformContextPtr ctxt, xmlNodePtr *sorts, int nbsorts); typedef enum { XSLT_FUNC_COPY=1, XSLT_FUNC_SORT, XSLT_FUNC_TEXT, XSLT_FUNC_ELEMENT, XSLT_FUNC_ATTRIBUTE, XSLT_FUNC_COMMENT, XSLT_FUNC_PI, XSLT_FUNC_COPYOF, XSLT_FUNC_VALUEOF, XSLT_FUNC_NUMBER, XSLT_FUNC_APPLYIMPORTS, XSLT_FUNC_CALLTEMPLATE, XSLT_FUNC_APPLYTEMPLATES, XSLT_FUNC_CHOOSE, XSLT_FUNC_IF, XSLT_FUNC_FOREACH, XSLT_FUNC_DOCUMENT, XSLT_FUNC_WITHPARAM, XSLT_FUNC_PARAM, XSLT_FUNC_VARIABLE, XSLT_FUNC_WHEN, XSLT_FUNC_EXTENSION #ifdef XSLT_REFACTORED , XSLT_FUNC_OTHERWISE, XSLT_FUNC_FALLBACK, XSLT_FUNC_MESSAGE, XSLT_FUNC_INCLUDE, XSLT_FUNC_ATTRSET, XSLT_FUNC_LITERAL_RESULT_ELEMENT, XSLT_FUNC_UNKOWN_FORWARDS_COMPAT #endif } xsltStyleType; /** * xsltElemPreCompDeallocator: * @comp: the #xsltElemPreComp to free up * * Deallocates an #xsltElemPreComp structure. */ typedef void (*xsltElemPreCompDeallocator) (xsltElemPreCompPtr comp); /** * xsltElemPreComp: * * The basic structure for compiled items of the AST of the XSLT processor. * This structure is also intended to be extended by extension implementors. * TODO: This is somehow not nice, since it has a "free" field, which * derived stylesheet-structs do not have. */ struct _xsltElemPreComp { xsltElemPreCompPtr next; /* next item in the global chained list held by xsltStylesheet. */ xsltStyleType type; /* type of the element */ xsltTransformFunction func; /* handling function */ xmlNodePtr inst; /* the node in the stylesheet's tree corresponding to this item */ /* end of common part */ xsltElemPreCompDeallocator free; /* the deallocator */ }; /** * xsltStylePreComp: * * The abstract basic structure for items of the XSLT processor. * This includes: * 1) compiled forms of XSLT instructions (xsl:if, xsl:attribute, etc.) * 2) compiled forms of literal result elements * 3) compiled forms of extension elements */ typedef struct _xsltStylePreComp xsltStylePreComp; typedef xsltStylePreComp *xsltStylePreCompPtr; #ifdef XSLT_REFACTORED /* * Some pointer-list utility functions. */ XSLTPUBFUN xsltPointerListPtr XSLTCALL xsltPointerListCreate (int initialSize); XSLTPUBFUN void XSLTCALL xsltPointerListFree (xsltPointerListPtr list); XSLTPUBFUN void XSLTCALL xsltPointerListClear (xsltPointerListPtr list); XSLTPUBFUN int XSLTCALL xsltPointerListAddSize (xsltPointerListPtr list, void *item, int initialSize); /************************************************************************ * * * Refactored structures * * * ************************************************************************/ typedef struct _xsltNsListContainer xsltNsListContainer; typedef xsltNsListContainer *xsltNsListContainerPtr; struct _xsltNsListContainer { xmlNsPtr *list; int totalNumber; int xpathNumber; }; /** * XSLT_ITEM_COMPATIBILITY_FIELDS: * * Fields for API compatibility to the structure * _xsltElemPreComp which is used for extension functions. * Note that @next is used for storage; it does not reflect a next * sibling in the tree. * TODO: Evaluate if we really need such a compatibility. */ #define XSLT_ITEM_COMPATIBILITY_FIELDS \ xsltElemPreCompPtr next;\ xsltStyleType type;\ xsltTransformFunction func;\ xmlNodePtr inst; /** * XSLT_ITEM_NAVIGATION_FIELDS: * * Currently empty. * TODO: It is intended to hold navigational fields in the future. */ #define XSLT_ITEM_NAVIGATION_FIELDS /* xsltStylePreCompPtr parent;\ xsltStylePreCompPtr children;\ xsltStylePreCompPtr nextItem; */ /** * XSLT_ITEM_NSINSCOPE_FIELDS: * * The in-scope namespaces. */ #define XSLT_ITEM_NSINSCOPE_FIELDS xsltNsListContainerPtr inScopeNs; /** * XSLT_ITEM_COMMON_FIELDS: * * Common fields used for all items. */ #define XSLT_ITEM_COMMON_FIELDS \ XSLT_ITEM_COMPATIBILITY_FIELDS \ XSLT_ITEM_NAVIGATION_FIELDS \ XSLT_ITEM_NSINSCOPE_FIELDS /** * _xsltStylePreComp: * * The abstract basic structure for items of the XSLT processor. * This includes: * 1) compiled forms of XSLT instructions (e.g. xsl:if, xsl:attribute, etc.) * 2) compiled forms of literal result elements * 3) various properties for XSLT instructions (e.g. xsl:when, * xsl:with-param) * * REVISIT TODO: Keep this structure equal to the fields * defined by XSLT_ITEM_COMMON_FIELDS */ struct _xsltStylePreComp { xsltElemPreCompPtr next; /* next item in the global chained list held by xsltStylesheet */ xsltStyleType type; /* type of the item */ xsltTransformFunction func; /* handling function */ xmlNodePtr inst; /* the node in the stylesheet's tree corresponding to this item. */ /* Currently no navigational fields. */ xsltNsListContainerPtr inScopeNs; }; /** * xsltStyleBasicEmptyItem: * * Abstract structure only used as a short-cut for * XSLT items with no extra fields. * NOTE that it is intended that this structure looks the same as * _xsltStylePreComp. */ typedef struct _xsltStyleBasicEmptyItem xsltStyleBasicEmptyItem; typedef xsltStyleBasicEmptyItem *xsltStyleBasicEmptyItemPtr; struct _xsltStyleBasicEmptyItem { XSLT_ITEM_COMMON_FIELDS }; /** * xsltStyleBasicExpressionItem: * * Abstract structure only used as a short-cut for * XSLT items with just an expression. */ typedef struct _xsltStyleBasicExpressionItem xsltStyleBasicExpressionItem; typedef xsltStyleBasicExpressionItem *xsltStyleBasicExpressionItemPtr; struct _xsltStyleBasicExpressionItem { XSLT_ITEM_COMMON_FIELDS const xmlChar *select; /* TODO: Change this to "expression". */ xmlXPathCompExprPtr comp; /* TODO: Change this to compExpr. */ }; /************************************************************************ * * * XSLT-instructions/declarations * * * ************************************************************************/ /** * xsltStyleItemElement: * * * * * */ typedef struct _xsltStyleItemElement xsltStyleItemElement; typedef xsltStyleItemElement *xsltStyleItemElementPtr; struct _xsltStyleItemElement { XSLT_ITEM_COMMON_FIELDS const xmlChar *use; int has_use; const xmlChar *name; int has_name; const xmlChar *ns; const xmlChar *nsPrefix; int has_ns; }; /** * xsltStyleItemAttribute: * * * * * */ typedef struct _xsltStyleItemAttribute xsltStyleItemAttribute; typedef xsltStyleItemAttribute *xsltStyleItemAttributePtr; struct _xsltStyleItemAttribute { XSLT_ITEM_COMMON_FIELDS const xmlChar *name; int has_name; const xmlChar *ns; const xmlChar *nsPrefix; int has_ns; }; /** * xsltStyleItemText: * * * * * */ typedef struct _xsltStyleItemText xsltStyleItemText; typedef xsltStyleItemText *xsltStyleItemTextPtr; struct _xsltStyleItemText { XSLT_ITEM_COMMON_FIELDS int noescape; /* text */ }; /** * xsltStyleItemComment: * * * * * */ typedef xsltStyleBasicEmptyItem xsltStyleItemComment; typedef xsltStyleItemComment *xsltStyleItemCommentPtr; /** * xsltStyleItemPI: * * * * * */ typedef struct _xsltStyleItemPI xsltStyleItemPI; typedef xsltStyleItemPI *xsltStyleItemPIPtr; struct _xsltStyleItemPI { XSLT_ITEM_COMMON_FIELDS const xmlChar *name; int has_name; }; /** * xsltStyleItemApplyImports: * * * */ typedef xsltStyleBasicEmptyItem xsltStyleItemApplyImports; typedef xsltStyleItemApplyImports *xsltStyleItemApplyImportsPtr; /** * xsltStyleItemApplyTemplates: * * * * * */ typedef struct _xsltStyleItemApplyTemplates xsltStyleItemApplyTemplates; typedef xsltStyleItemApplyTemplates *xsltStyleItemApplyTemplatesPtr; struct _xsltStyleItemApplyTemplates { XSLT_ITEM_COMMON_FIELDS const xmlChar *mode; /* apply-templates */ const xmlChar *modeURI; /* apply-templates */ const xmlChar *select; /* sort, copy-of, value-of, apply-templates */ xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ /* TODO: with-params */ }; /** * xsltStyleItemCallTemplate: * * * * * */ typedef struct _xsltStyleItemCallTemplate xsltStyleItemCallTemplate; typedef xsltStyleItemCallTemplate *xsltStyleItemCallTemplatePtr; struct _xsltStyleItemCallTemplate { XSLT_ITEM_COMMON_FIELDS xsltTemplatePtr templ; /* call-template */ const xmlChar *name; /* element, attribute, pi */ int has_name; /* element, attribute, pi */ const xmlChar *ns; /* element */ int has_ns; /* element */ /* TODO: with-params */ }; /** * xsltStyleItemCopy: * * * * * */ typedef struct _xsltStyleItemCopy xsltStyleItemCopy; typedef xsltStyleItemCopy *xsltStyleItemCopyPtr; struct _xsltStyleItemCopy { XSLT_ITEM_COMMON_FIELDS const xmlChar *use; /* copy, element */ int has_use; /* copy, element */ }; /** * xsltStyleItemIf: * * * * * */ typedef struct _xsltStyleItemIf xsltStyleItemIf; typedef xsltStyleItemIf *xsltStyleItemIfPtr; struct _xsltStyleItemIf { XSLT_ITEM_COMMON_FIELDS const xmlChar *test; /* if */ xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ }; /** * xsltStyleItemCopyOf: * * * */ typedef xsltStyleBasicExpressionItem xsltStyleItemCopyOf; typedef xsltStyleItemCopyOf *xsltStyleItemCopyOfPtr; /** * xsltStyleItemValueOf: * * * */ typedef struct _xsltStyleItemValueOf xsltStyleItemValueOf; typedef xsltStyleItemValueOf *xsltStyleItemValueOfPtr; struct _xsltStyleItemValueOf { XSLT_ITEM_COMMON_FIELDS const xmlChar *select; xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ int noescape; }; /** * xsltStyleItemNumber: * * * */ typedef struct _xsltStyleItemNumber xsltStyleItemNumber; typedef xsltStyleItemNumber *xsltStyleItemNumberPtr; struct _xsltStyleItemNumber { XSLT_ITEM_COMMON_FIELDS xsltNumberData numdata; /* number */ }; /** * xsltStyleItemChoose: * * * * * */ typedef xsltStyleBasicEmptyItem xsltStyleItemChoose; typedef xsltStyleItemChoose *xsltStyleItemChoosePtr; /** * xsltStyleItemFallback: * * * * * */ typedef xsltStyleBasicEmptyItem xsltStyleItemFallback; typedef xsltStyleItemFallback *xsltStyleItemFallbackPtr; /** * xsltStyleItemForEach: * * * * * */ typedef xsltStyleBasicExpressionItem xsltStyleItemForEach; typedef xsltStyleItemForEach *xsltStyleItemForEachPtr; /** * xsltStyleItemMessage: * * * * * */ typedef struct _xsltStyleItemMessage xsltStyleItemMessage; typedef xsltStyleItemMessage *xsltStyleItemMessagePtr; struct _xsltStyleItemMessage { XSLT_ITEM_COMMON_FIELDS int terminate; }; /** * xsltStyleItemDocument: * * NOTE: This is not an instruction of XSLT 1.0. */ typedef struct _xsltStyleItemDocument xsltStyleItemDocument; typedef xsltStyleItemDocument *xsltStyleItemDocumentPtr; struct _xsltStyleItemDocument { XSLT_ITEM_COMMON_FIELDS int ver11; /* assigned: in xsltDocumentComp; read: nowhere; TODO: Check if we need. */ const xmlChar *filename; /* document URL */ int has_filename; }; /************************************************************************ * * * Non-instructions (actually properties of instructions/declarations) * * * ************************************************************************/ /** * xsltStyleBasicItemVariable: * * Basic struct for xsl:variable, xsl:param and xsl:with-param. * It's currently important to have equal fields, since * xsltParseStylesheetCallerParam() is used with xsl:with-param from * the xslt side and with xsl:param from the exslt side (in * exsltFuncFunctionFunction()). * * FUTURE NOTE: In XSLT 2.0 xsl:param, xsl:variable and xsl:with-param * have additional different fields. */ typedef struct _xsltStyleBasicItemVariable xsltStyleBasicItemVariable; typedef xsltStyleBasicItemVariable *xsltStyleBasicItemVariablePtr; struct _xsltStyleBasicItemVariable { XSLT_ITEM_COMMON_FIELDS const xmlChar *select; xmlXPathCompExprPtr comp; const xmlChar *name; int has_name; const xmlChar *ns; int has_ns; }; /** * xsltStyleItemVariable: * * * * * */ typedef xsltStyleBasicItemVariable xsltStyleItemVariable; typedef xsltStyleItemVariable *xsltStyleItemVariablePtr; /** * xsltStyleItemParam: * * * * * */ typedef struct _xsltStyleItemParam xsltStyleItemParam; typedef xsltStyleItemParam *xsltStyleItemParamPtr; struct _xsltStyleItemParam { XSLT_ITEM_COMMON_FIELDS const xmlChar *select; xmlXPathCompExprPtr comp; const xmlChar *name; int has_name; const xmlChar *ns; int has_ns; }; /** * xsltStyleItemWithParam: * * * * */ typedef xsltStyleBasicItemVariable xsltStyleItemWithParam; typedef xsltStyleItemWithParam *xsltStyleItemWithParamPtr; /** * xsltStyleItemSort: * * Reflects the XSLT xsl:sort item. * Allowed parents: xsl:apply-templates, xsl:for-each * */ typedef struct _xsltStyleItemSort xsltStyleItemSort; typedef xsltStyleItemSort *xsltStyleItemSortPtr; struct _xsltStyleItemSort { XSLT_ITEM_COMMON_FIELDS const xmlChar *stype; /* sort */ int has_stype; /* sort */ int number; /* sort */ const xmlChar *order; /* sort */ int has_order; /* sort */ int descending; /* sort */ const xmlChar *lang; /* sort */ int has_lang; /* sort */ xsltLocale locale; /* sort */ const xmlChar *case_order; /* sort */ int lower_first; /* sort */ const xmlChar *use; int has_use; const xmlChar *select; /* sort, copy-of, value-of, apply-templates */ xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ }; /** * xsltStyleItemWhen: * * * * * Allowed parent: xsl:choose */ typedef struct _xsltStyleItemWhen xsltStyleItemWhen; typedef xsltStyleItemWhen *xsltStyleItemWhenPtr; struct _xsltStyleItemWhen { XSLT_ITEM_COMMON_FIELDS const xmlChar *test; xmlXPathCompExprPtr comp; }; /** * xsltStyleItemOtherwise: * * Allowed parent: xsl:choose * * * */ typedef struct _xsltStyleItemOtherwise xsltStyleItemOtherwise; typedef xsltStyleItemOtherwise *xsltStyleItemOtherwisePtr; struct _xsltStyleItemOtherwise { XSLT_ITEM_COMMON_FIELDS }; typedef struct _xsltStyleItemInclude xsltStyleItemInclude; typedef xsltStyleItemInclude *xsltStyleItemIncludePtr; struct _xsltStyleItemInclude { XSLT_ITEM_COMMON_FIELDS xsltDocumentPtr include; }; /************************************************************************ * * * XSLT elements in forwards-compatible mode * * * ************************************************************************/ typedef struct _xsltStyleItemUknown xsltStyleItemUknown; typedef xsltStyleItemUknown *xsltStyleItemUknownPtr; struct _xsltStyleItemUknown { XSLT_ITEM_COMMON_FIELDS }; /************************************************************************ * * * Extension elements * * * ************************************************************************/ /* * xsltStyleItemExtElement: * * Reflects extension elements. * * NOTE: Due to the fact that the structure xsltElemPreComp is most * probably already heavily in use out there by users, so we cannot * easily change it, we'll create an intermediate structure which will * hold an xsltElemPreCompPtr. * BIG NOTE: The only problem I see here is that the user processes the * content of the stylesheet tree, possibly he'll lookup the node->psvi * fields in order to find subsequent extension functions. * In this case, the user's code will break, since the node->psvi * field will hold now the xsltStyleItemExtElementPtr and not * the xsltElemPreCompPtr. * However the place where the structure is anchored in the node-tree, * namely node->psvi, has beed already once been moved from node->_private * to node->psvi, so we have a precedent here, which, I think, should allow * us to change such semantics without headaches. */ typedef struct _xsltStyleItemExtElement xsltStyleItemExtElement; typedef xsltStyleItemExtElement *xsltStyleItemExtElementPtr; struct _xsltStyleItemExtElement { XSLT_ITEM_COMMON_FIELDS xsltElemPreCompPtr item; }; /************************************************************************ * * * Literal result elements * * * ************************************************************************/ typedef struct _xsltEffectiveNs xsltEffectiveNs; typedef xsltEffectiveNs *xsltEffectiveNsPtr; struct _xsltEffectiveNs { xsltEffectiveNsPtr nextInStore; /* storage next */ xsltEffectiveNsPtr next; /* next item in the list */ const xmlChar *prefix; const xmlChar *nsName; /* * Indicates if eclared on the literal result element; dunno if really * needed. */ int holdByElem; }; /* * Info for literal result elements. * This will be set on the elem->psvi field and will be * shared by literal result elements, which have the same * excluded result namespaces; i.e., this *won't* be created uniquely * for every literal result element. */ typedef struct _xsltStyleItemLRElementInfo xsltStyleItemLRElementInfo; typedef xsltStyleItemLRElementInfo *xsltStyleItemLRElementInfoPtr; struct _xsltStyleItemLRElementInfo { XSLT_ITEM_COMMON_FIELDS /* * @effectiveNs is the set of effective ns-nodes * on the literal result element, which will be added to the result * element if not already existing in the result tree. * This means that excluded namespaces (via exclude-result-prefixes, * extension-element-prefixes and the XSLT namespace) not added * to the set. * Namespace-aliasing was applied on the @effectiveNs. */ xsltEffectiveNsPtr effectiveNs; }; #ifdef XSLT_REFACTORED typedef struct _xsltNsAlias xsltNsAlias; typedef xsltNsAlias *xsltNsAliasPtr; struct _xsltNsAlias { xsltNsAliasPtr next; /* next in the list */ xmlNsPtr literalNs; xmlNsPtr targetNs; xmlDocPtr docOfTargetNs; }; #endif #ifdef XSLT_REFACTORED_XSLT_NSCOMP typedef struct _xsltNsMap xsltNsMap; typedef xsltNsMap *xsltNsMapPtr; struct _xsltNsMap { xsltNsMapPtr next; /* next in the list */ xmlDocPtr doc; xmlNodePtr elem; /* the element holding the ns-decl */ xmlNsPtr ns; /* the xmlNs structure holding the XML namespace name */ const xmlChar *origNsName; /* the original XML namespace name */ const xmlChar *newNsName; /* the mapped XML namespace name */ }; #endif /************************************************************************ * * * Compile-time structures for *internal* use only * * * ************************************************************************/ typedef struct _xsltPrincipalStylesheetData xsltPrincipalStylesheetData; typedef xsltPrincipalStylesheetData *xsltPrincipalStylesheetDataPtr; typedef struct _xsltNsList xsltNsList; typedef xsltNsList *xsltNsListPtr; struct _xsltNsList { xsltNsListPtr next; /* next in the list */ xmlNsPtr ns; }; /* * xsltVarInfo: * * Used at compilation time for parameters and variables. */ typedef struct _xsltVarInfo xsltVarInfo; typedef xsltVarInfo *xsltVarInfoPtr; struct _xsltVarInfo { xsltVarInfoPtr next; /* next in the list */ xsltVarInfoPtr prev; int depth; /* the depth in the tree */ const xmlChar *name; const xmlChar *nsName; }; /** * xsltCompilerNodeInfo: * * Per-node information during compile-time. */ typedef struct _xsltCompilerNodeInfo xsltCompilerNodeInfo; typedef xsltCompilerNodeInfo *xsltCompilerNodeInfoPtr; struct _xsltCompilerNodeInfo { xsltCompilerNodeInfoPtr next; xsltCompilerNodeInfoPtr prev; xmlNodePtr node; int depth; xsltTemplatePtr templ; /* The owning template */ int category; /* XSLT element, LR-element or extension element */ xsltStyleType type; xsltElemPreCompPtr item; /* The compiled information */ /* The current in-scope namespaces */ xsltNsListContainerPtr inScopeNs; /* The current excluded result namespaces */ xsltPointerListPtr exclResultNs; /* The current extension instruction namespaces */ xsltPointerListPtr extElemNs; /* The current info for literal result elements. */ xsltStyleItemLRElementInfoPtr litResElemInfo; /* * Set to 1 if in-scope namespaces changed, * or excluded result namespaces changed, * or extension element namespaces changed. * This will trigger creation of new infos * for literal result elements. */ int nsChanged; int preserveWhitespace; int stripWhitespace; int isRoot; /* whether this is the stylesheet's root node */ int forwardsCompat; /* whether forwards-compatible mode is enabled */ /* whether the content of an extension element was processed */ int extContentHandled; /* the type of the current child */ xsltStyleType curChildType; }; /** * XSLT_CCTXT: * * get pointer to compiler context */ #define XSLT_CCTXT(style) ((xsltCompilerCtxtPtr) style->compCtxt) typedef enum { XSLT_ERROR_SEVERITY_ERROR = 0, XSLT_ERROR_SEVERITY_WARNING } xsltErrorSeverityType; typedef struct _xsltCompilerCtxt xsltCompilerCtxt; typedef xsltCompilerCtxt *xsltCompilerCtxtPtr; struct _xsltCompilerCtxt { void *errorCtxt; /* user specific error context */ /* * used for error/warning reports; e.g. XSLT_ERROR_SEVERITY_WARNING */ xsltErrorSeverityType errSeverity; int warnings; /* TODO: number of warnings found at compilation */ int errors; /* TODO: number of errors found at compilation */ xmlDictPtr dict; xsltStylesheetPtr style; int simplified; /* whether this is a simplified stylesheet */ /* TODO: structured/unstructured error contexts. */ int depth; /* Current depth of processing */ xsltCompilerNodeInfoPtr inode; xsltCompilerNodeInfoPtr inodeList; xsltCompilerNodeInfoPtr inodeLast; xsltPointerListPtr tmpList; /* Used for various purposes */ /* * The XSLT version as specified by the stylesheet's root element. */ int isInclude; int hasForwardsCompat; /* whether forwards-compatible mode was used in a parsing episode */ int maxNodeInfos; /* TEMP TODO: just for the interest */ int maxLREs; /* TEMP TODO: just for the interest */ /* * In order to keep the old behaviour, applying strict rules of * the spec can be turned off. This has effect only on special * mechanisms like whitespace-stripping in the stylesheet. */ int strict; xsltPrincipalStylesheetDataPtr psData; xsltStyleItemUknownPtr unknownItem; int hasNsAliases; /* Indicator if there was an xsl:namespace-alias. */ xsltNsAliasPtr nsAliases; xsltVarInfoPtr ivars; /* Storage of local in-scope variables/params. */ xsltVarInfoPtr ivar; /* topmost local variable/param. */ }; #else /* XSLT_REFACTORED */ /* * The old structures before refactoring. */ /** * _xsltStylePreComp: * * The in-memory structure corresponding to XSLT stylesheet constructs * precomputed data. */ struct _xsltStylePreComp { xsltElemPreCompPtr next; /* chained list */ xsltStyleType type; /* type of the element */ xsltTransformFunction func; /* handling function */ xmlNodePtr inst; /* the instruction */ /* * Pre computed values. */ const xmlChar *stype; /* sort */ int has_stype; /* sort */ int number; /* sort */ const xmlChar *order; /* sort */ int has_order; /* sort */ int descending; /* sort */ const xmlChar *lang; /* sort */ int has_lang; /* sort */ xsltLocale locale; /* sort */ const xmlChar *case_order; /* sort */ int lower_first; /* sort */ const xmlChar *use; /* copy, element */ int has_use; /* copy, element */ int noescape; /* text */ const xmlChar *name; /* element, attribute, pi */ int has_name; /* element, attribute, pi */ const xmlChar *ns; /* element */ int has_ns; /* element */ const xmlChar *mode; /* apply-templates */ const xmlChar *modeURI; /* apply-templates */ const xmlChar *test; /* if */ xsltTemplatePtr templ; /* call-template */ const xmlChar *select; /* sort, copy-of, value-of, apply-templates */ int ver11; /* document */ const xmlChar *filename; /* document URL */ int has_filename; /* document */ xsltNumberData numdata; /* number */ xmlXPathCompExprPtr comp; /* a precompiled XPath expression */ xmlNsPtr *nsList; /* the namespaces in scope */ int nsNr; /* the number of namespaces in scope */ }; #endif /* XSLT_REFACTORED */ /* * The in-memory structure corresponding to an XSLT Variable * or Param. */ typedef struct _xsltStackElem xsltStackElem; typedef xsltStackElem *xsltStackElemPtr; struct _xsltStackElem { struct _xsltStackElem *next;/* chained list */ xsltStylePreCompPtr comp; /* the compiled form */ int computed; /* was the evaluation done */ const xmlChar *name; /* the local part of the name QName */ const xmlChar *nameURI; /* the URI part of the name QName */ const xmlChar *select; /* the eval string */ xmlNodePtr tree; /* the sequence constructor if no eval string or the location */ xmlXPathObjectPtr value; /* The value if computed */ xmlDocPtr fragment; /* The Result Tree Fragments (needed for XSLT 1.0) which are bound to the variable's lifetime. */ int level; /* the depth in the tree; -1 if persistent (e.g. a given xsl:with-param) */ xsltTransformContextPtr context; /* The transformation context; needed to cache the variables */ int flags; }; #ifdef XSLT_REFACTORED struct _xsltPrincipalStylesheetData { /* * Namespace dictionary for ns-prefixes and ns-names: * TODO: Shared between stylesheets, and XPath mechanisms. * Not used yet. */ xmlDictPtr namespaceDict; /* * Global list of in-scope namespaces. */ xsltPointerListPtr inScopeNamespaces; /* * Global list of information for [xsl:]excluded-result-prefixes. */ xsltPointerListPtr exclResultNamespaces; /* * Global list of information for [xsl:]extension-element-prefixes. */ xsltPointerListPtr extElemNamespaces; xsltEffectiveNsPtr effectiveNs; #ifdef XSLT_REFACTORED_XSLT_NSCOMP /* * Namespace name map to get rid of string comparison of namespace names. */ xsltNsMapPtr nsMap; #endif }; #endif /* * Note that we added a @compCtxt field to anchor an stylesheet compilation * context, since, due to historical reasons, various compile-time function * take only the stylesheet as argument and not a compilation context. */ struct _xsltStylesheet { /* * The stylesheet import relation is kept as a tree. */ struct _xsltStylesheet *parent; struct _xsltStylesheet *next; struct _xsltStylesheet *imports; xsltDocumentPtr docList; /* the include document list */ /* * General data on the style sheet document. */ xmlDocPtr doc; /* the parsed XML stylesheet */ xmlHashTablePtr stripSpaces;/* the hash table of the strip-space and preserve space elements */ int stripAll; /* strip-space * (1) preserve-space * (-1) */ xmlHashTablePtr cdataSection;/* the hash table of the cdata-section */ /* * Global variable or parameters. */ xsltStackElemPtr variables; /* linked list of param and variables */ /* * Template descriptions. */ xsltTemplatePtr templates; /* the ordered list of templates */ xmlHashTablePtr templatesHash; /* hash table or wherever compiled templates information is stored */ struct _xsltCompMatch *rootMatch; /* template based on / */ struct _xsltCompMatch *keyMatch; /* template based on key() */ struct _xsltCompMatch *elemMatch; /* template based on * */ struct _xsltCompMatch *attrMatch; /* template based on @* */ struct _xsltCompMatch *parentMatch; /* template based on .. */ struct _xsltCompMatch *textMatch; /* template based on text() */ struct _xsltCompMatch *piMatch; /* template based on processing-instruction() */ struct _xsltCompMatch *commentMatch; /* template based on comment() */ /* * Namespace aliases. * NOTE: Not used in the refactored code. */ xmlHashTablePtr nsAliases; /* the namespace alias hash tables */ /* * Attribute sets. */ xmlHashTablePtr attributeSets;/* the attribute sets hash tables */ /* * Namespaces. * TODO: Eliminate this. */ xmlHashTablePtr nsHash; /* the set of namespaces in use: ATTENTION: This is used for execution of XPath expressions; unfortunately it restricts the stylesheet to have distinct prefixes. TODO: We need to get rid of this. */ void *nsDefs; /* ATTENTION TODO: This is currently used to store xsltExtDefPtr (in extensions.c) and *not* xmlNsPtr. */ /* * Key definitions. */ void *keys; /* key definitions */ /* * Output related stuff. */ xmlChar *method; /* the output method */ xmlChar *methodURI; /* associated namespace if any */ xmlChar *version; /* version string */ xmlChar *encoding; /* encoding string */ int omitXmlDeclaration; /* omit-xml-declaration = "yes" | "no" */ /* * Number formatting. */ xsltDecimalFormatPtr decimalFormat; int standalone; /* standalone = "yes" | "no" */ xmlChar *doctypePublic; /* doctype-public string */ xmlChar *doctypeSystem; /* doctype-system string */ int indent; /* should output being indented */ xmlChar *mediaType; /* media-type string */ /* * Precomputed blocks. */ xsltElemPreCompPtr preComps;/* list of precomputed blocks */ int warnings; /* number of warnings found at compilation */ int errors; /* number of errors found at compilation */ xmlChar *exclPrefix; /* last excluded prefixes */ xmlChar **exclPrefixTab; /* array of excluded prefixes */ int exclPrefixNr; /* number of excluded prefixes in scope */ int exclPrefixMax; /* size of the array */ void *_private; /* user defined data */ /* * Extensions. */ xmlHashTablePtr extInfos; /* the extension data */ int extrasNr; /* the number of extras required */ /* * For keeping track of nested includes */ xsltDocumentPtr includes; /* points to last nested include */ /* * dictionary: shared between stylesheet, context and documents. */ xmlDictPtr dict; /* * precompiled attribute value templates. */ void *attVTs; /* * if namespace-alias has an alias for the default stylesheet prefix * NOTE: Not used in the refactored code. */ const xmlChar *defaultAlias; /* * bypass pre-processing (already done) (used in imports) */ int nopreproc; /* * all document text strings were internalized */ int internalized; /* * Literal Result Element as Stylesheet c.f. section 2.3 */ int literal_result; /* * The principal stylesheet */ xsltStylesheetPtr principal; #ifdef XSLT_REFACTORED /* * Compilation context used during compile-time. */ xsltCompilerCtxtPtr compCtxt; /* TODO: Change this to (void *). */ xsltPrincipalStylesheetDataPtr principalData; #endif /* * Forwards-compatible processing */ int forwards_compatible; xmlHashTablePtr namedTemplates; /* hash table of named templates */ xmlXPathContextPtr xpathCtxt; }; typedef struct _xsltTransformCache xsltTransformCache; typedef xsltTransformCache *xsltTransformCachePtr; struct _xsltTransformCache { xmlDocPtr RVT; int nbRVT; xsltStackElemPtr stackItems; int nbStackItems; #ifdef XSLT_DEBUG_PROFILE_CACHE int dbgCachedRVTs; int dbgReusedRVTs; int dbgCachedVars; int dbgReusedVars; #endif }; /* * The in-memory structure corresponding to an XSLT Transformation. */ typedef enum { XSLT_OUTPUT_XML = 0, XSLT_OUTPUT_HTML, XSLT_OUTPUT_TEXT } xsltOutputType; typedef enum { XSLT_STATE_OK = 0, XSLT_STATE_ERROR, XSLT_STATE_STOPPED } xsltTransformState; struct _xsltTransformContext { xsltStylesheetPtr style; /* the stylesheet used */ xsltOutputType type; /* the type of output */ xsltTemplatePtr templ; /* the current template */ int templNr; /* Nb of templates in the stack */ int templMax; /* Size of the templtes stack */ xsltTemplatePtr *templTab; /* the template stack */ xsltStackElemPtr vars; /* the current variable list */ int varsNr; /* Nb of variable list in the stack */ int varsMax; /* Size of the variable list stack */ xsltStackElemPtr *varsTab; /* the variable list stack */ int varsBase; /* the var base for current templ */ /* * Extensions */ xmlHashTablePtr extFunctions; /* the extension functions */ xmlHashTablePtr extElements; /* the extension elements */ xmlHashTablePtr extInfos; /* the extension data */ const xmlChar *mode; /* the current mode */ const xmlChar *modeURI; /* the current mode URI */ xsltDocumentPtr docList; /* the document list */ xsltDocumentPtr document; /* the current source document; can be NULL if an RTF */ xmlNodePtr node; /* the current node being processed */ xmlNodeSetPtr nodeList; /* the current node list */ /* xmlNodePtr current; the node */ xmlDocPtr output; /* the resulting document */ xmlNodePtr insert; /* the insertion node */ xmlXPathContextPtr xpathCtxt; /* the XPath context */ xsltTransformState state; /* the current state */ /* * Global variables */ xmlHashTablePtr globalVars; /* the global variables and params */ xmlNodePtr inst; /* the instruction in the stylesheet */ int xinclude; /* should XInclude be processed */ const char * outputFile; /* the output URI if known */ int profile; /* is this run profiled */ long prof; /* the current profiled value */ int profNr; /* Nb of templates in the stack */ int profMax; /* Size of the templtaes stack */ long *profTab; /* the profile template stack */ void *_private; /* user defined data */ int extrasNr; /* the number of extras used */ int extrasMax; /* the number of extras allocated */ xsltRuntimeExtraPtr extras; /* extra per runtime information */ xsltDocumentPtr styleList; /* the stylesheet docs list */ void * sec; /* the security preferences if any */ xmlGenericErrorFunc error; /* a specific error handler */ void * errctx; /* context for the error handler */ xsltSortFunc sortfunc; /* a ctxt specific sort routine */ /* * handling of temporary Result Value Tree * (XSLT 1.0 term: "Result Tree Fragment") */ xmlDocPtr tmpRVT; /* list of RVT without persistance */ xmlDocPtr persistRVT; /* list of persistant RVTs */ int ctxtflags; /* context processing flags */ /* * Speed optimization when coalescing text nodes */ const xmlChar *lasttext; /* last text node content */ int lasttsize; /* last text node size */ int lasttuse; /* last text node use */ /* * Per Context Debugging */ int debugStatus; /* the context level debug status */ unsigned long* traceCode; /* pointer to the variable holding the mask */ int parserOptions; /* parser options xmlParserOption */ /* * dictionary: shared between stylesheet, context and documents. */ xmlDictPtr dict; xmlDocPtr tmpDoc; /* Obsolete; not used in the library. */ /* * all document text strings are internalized */ int internalized; int nbKeys; int hasTemplKeyPatterns; xsltTemplatePtr currentTemplateRule; /* the Current Template Rule */ xmlNodePtr initialContextNode; xmlDocPtr initialContextDoc; xsltTransformCachePtr cache; void *contextVariable; /* the current variable item */ xmlDocPtr localRVT; /* list of local tree fragments; will be freed when the instruction which created the fragment exits */ xmlDocPtr localRVTBase; /* Obsolete */ int keyInitLevel; /* Needed to catch recursive keys issues */ int depth; /* Needed to catch recursions */ int maxTemplateDepth; int maxTemplateVars; unsigned long opLimit; unsigned long opCount; }; /** * CHECK_STOPPED: * * Macro to check if the XSLT processing should be stopped. * Will return from the function. */ #define CHECK_STOPPED if (ctxt->state == XSLT_STATE_STOPPED) return; /** * CHECK_STOPPEDE: * * Macro to check if the XSLT processing should be stopped. * Will goto the error: label. */ #define CHECK_STOPPEDE if (ctxt->state == XSLT_STATE_STOPPED) goto error; /** * CHECK_STOPPED0: * * Macro to check if the XSLT processing should be stopped. * Will return from the function with a 0 value. */ #define CHECK_STOPPED0 if (ctxt->state == XSLT_STATE_STOPPED) return(0); /* * The macro XML_CAST_FPTR is a hack to avoid a gcc warning about * possible incompatibilities between function pointers and object * pointers. It is defined in libxml/hash.h within recent versions * of libxml2, but is put here for compatibility. */ #ifndef XML_CAST_FPTR /** * XML_CAST_FPTR: * @fptr: pointer to a function * * Macro to do a casting from an object pointer to a * function pointer without encountering a warning from * gcc * * #define XML_CAST_FPTR(fptr) (*(void **)(&fptr)) * This macro violated ISO C aliasing rules (gcc4 on s390 broke) * so it is disabled now */ #define XML_CAST_FPTR(fptr) fptr #endif /* * Functions associated to the internal types xsltDecimalFormatPtr xsltDecimalFormatGetByName(xsltStylesheetPtr sheet, xmlChar *name); */ XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltNewStylesheet (void); XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltParseStylesheetFile (const xmlChar* filename); XSLTPUBFUN void XSLTCALL xsltFreeStylesheet (xsltStylesheetPtr style); XSLTPUBFUN int XSLTCALL xsltIsBlank (xmlChar *str); XSLTPUBFUN void XSLTCALL xsltFreeStackElemList (xsltStackElemPtr elem); XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL xsltDecimalFormatGetByName(xsltStylesheetPtr style, xmlChar *name); XSLTPUBFUN xsltDecimalFormatPtr XSLTCALL xsltDecimalFormatGetByQName(xsltStylesheetPtr style, const xmlChar *nsUri, const xmlChar *name); XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltParseStylesheetProcess(xsltStylesheetPtr ret, xmlDocPtr doc); XSLTPUBFUN void XSLTCALL xsltParseStylesheetOutput(xsltStylesheetPtr style, xmlNodePtr cur); XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltParseStylesheetDoc (xmlDocPtr doc); XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltParseStylesheetImportedDoc(xmlDocPtr doc, xsltStylesheetPtr style); XSLTPUBFUN int XSLTCALL xsltParseStylesheetUser(xsltStylesheetPtr style, xmlDocPtr doc); XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltLoadStylesheetPI (xmlDocPtr doc); XSLTPUBFUN void XSLTCALL xsltNumberFormat (xsltTransformContextPtr ctxt, xsltNumberDataPtr data, xmlNodePtr node); XSLTPUBFUN xmlXPathError XSLTCALL xsltFormatNumberConversion(xsltDecimalFormatPtr self, xmlChar *format, double number, xmlChar **result); XSLTPUBFUN void XSLTCALL xsltParseTemplateContent(xsltStylesheetPtr style, xmlNodePtr templ); XSLTPUBFUN int XSLTCALL xsltAllocateExtra (xsltStylesheetPtr style); XSLTPUBFUN int XSLTCALL xsltAllocateExtraCtxt (xsltTransformContextPtr ctxt); /* * Extra functions for Result Value Trees */ XSLTPUBFUN xmlDocPtr XSLTCALL xsltCreateRVT (xsltTransformContextPtr ctxt); XSLTPUBFUN int XSLTCALL xsltRegisterTmpRVT (xsltTransformContextPtr ctxt, xmlDocPtr RVT); XSLTPUBFUN int XSLTCALL xsltRegisterLocalRVT (xsltTransformContextPtr ctxt, xmlDocPtr RVT); XSLTPUBFUN int XSLTCALL xsltRegisterPersistRVT (xsltTransformContextPtr ctxt, xmlDocPtr RVT); XSLTPUBFUN int XSLTCALL xsltExtensionInstructionResultRegister( xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj); XSLTPUBFUN int XSLTCALL xsltExtensionInstructionResultFinalize( xsltTransformContextPtr ctxt); XSLTPUBFUN int XSLTCALL xsltFlagRVTs( xsltTransformContextPtr ctxt, xmlXPathObjectPtr obj, void *val); XSLTPUBFUN void XSLTCALL xsltFreeRVTs (xsltTransformContextPtr ctxt); XSLTPUBFUN void XSLTCALL xsltReleaseRVT (xsltTransformContextPtr ctxt, xmlDocPtr RVT); /* * Extra functions for Attribute Value Templates */ XSLTPUBFUN void XSLTCALL xsltCompileAttr (xsltStylesheetPtr style, xmlAttrPtr attr); XSLTPUBFUN xmlChar * XSLTCALL xsltEvalAVT (xsltTransformContextPtr ctxt, void *avt, xmlNodePtr node); XSLTPUBFUN void XSLTCALL xsltFreeAVTList (void *avt); /* * Extra function for successful xsltCleanupGlobals / xsltInit sequence. */ XSLTPUBFUN void XSLTCALL xsltUninit (void); /************************************************************************ * * * Compile-time functions for *internal* use only * * * ************************************************************************/ #ifdef XSLT_REFACTORED XSLTPUBFUN void XSLTCALL xsltParseSequenceConstructor( xsltCompilerCtxtPtr cctxt, xmlNodePtr start); XSLTPUBFUN int XSLTCALL xsltParseAnyXSLTElem (xsltCompilerCtxtPtr cctxt, xmlNodePtr elem); #ifdef XSLT_REFACTORED_XSLT_NSCOMP XSLTPUBFUN int XSLTCALL xsltRestoreDocumentNamespaces( xsltNsMapPtr ns, xmlDocPtr doc); #endif #endif /* XSLT_REFACTORED */ /************************************************************************ * * * Transformation-time functions for *internal* use only * * * ************************************************************************/ XSLTPUBFUN int XSLTCALL xsltInitCtxtKey (xsltTransformContextPtr ctxt, xsltDocumentPtr doc, xsltKeyDefPtr keyd); XSLTPUBFUN int XSLTCALL xsltInitAllDocKeys (xsltTransformContextPtr ctxt); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_H__ */ PK!آlibxslt/numbersInternals.hnu[/* * Summary: Implementation of the XSLT number functions * Description: Implementation of the XSLT number functions * * Copy: See Copyright for the status of this software. * * Author: Bjorn Reese and Daniel Veillard */ #ifndef __XML_XSLT_NUMBERSINTERNALS_H__ #define __XML_XSLT_NUMBERSINTERNALS_H__ #include #include "xsltexports.h" #ifdef __cplusplus extern "C" { #endif struct _xsltCompMatch; /** * xsltNumberData: * * This data structure is just a wrapper to pass xsl:number data in. */ typedef struct _xsltNumberData xsltNumberData; typedef xsltNumberData *xsltNumberDataPtr; struct _xsltNumberData { const xmlChar *level; const xmlChar *count; const xmlChar *from; const xmlChar *value; const xmlChar *format; int has_format; int digitsPerGroup; int groupingCharacter; int groupingCharacterLen; xmlDocPtr doc; xmlNodePtr node; struct _xsltCompMatch *countPat; struct _xsltCompMatch *fromPat; /* * accelerators */ }; /** * xsltFormatNumberInfo,: * * This data structure lists the various parameters needed to format numbers. */ typedef struct _xsltFormatNumberInfo xsltFormatNumberInfo; typedef xsltFormatNumberInfo *xsltFormatNumberInfoPtr; struct _xsltFormatNumberInfo { int integer_hash; /* Number of '#' in integer part */ int integer_digits; /* Number of '0' in integer part */ int frac_digits; /* Number of '0' in fractional part */ int frac_hash; /* Number of '#' in fractional part */ int group; /* Number of chars per display 'group' */ int multiplier; /* Scaling for percent or permille */ char add_decimal; /* Flag for whether decimal point appears in pattern */ char is_multiplier_set; /* Flag to catch multiple occurences of percent/permille */ char is_negative_pattern;/* Flag for processing -ve prefix/suffix */ }; #ifdef __cplusplus } #endif #endif /* __XML_XSLT_NUMBERSINTERNALS_H__ */ PK!V>>libxslt/pattern.hnu[/* * Summary: interface for the pattern matching used in template matches. * Description: the implementation of the lookup of the right template * for a given node must be really fast in order to keep * decent performances. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_PATTERN_H__ #define __XML_XSLT_PATTERN_H__ #include "xsltInternals.h" #include "xsltexports.h" #ifdef __cplusplus extern "C" { #endif /** * xsltCompMatch: * * Data structure used for the implementation of patterns. * It is kept private (in pattern.c). */ typedef struct _xsltCompMatch xsltCompMatch; typedef xsltCompMatch *xsltCompMatchPtr; /* * Pattern related interfaces. */ XSLTPUBFUN xsltCompMatchPtr XSLTCALL xsltCompilePattern (const xmlChar *pattern, xmlDocPtr doc, xmlNodePtr node, xsltStylesheetPtr style, xsltTransformContextPtr runtime); XSLTPUBFUN void XSLTCALL xsltFreeCompMatchList (xsltCompMatchPtr comp); XSLTPUBFUN int XSLTCALL xsltTestCompMatchList (xsltTransformContextPtr ctxt, xmlNodePtr node, xsltCompMatchPtr comp); XSLTPUBFUN void XSLTCALL xsltCompMatchClearCache (xsltTransformContextPtr ctxt, xsltCompMatchPtr comp); XSLTPUBFUN void XSLTCALL xsltNormalizeCompSteps (void *payload, void *data, const xmlChar *name); /* * Template related interfaces. */ XSLTPUBFUN int XSLTCALL xsltAddTemplate (xsltStylesheetPtr style, xsltTemplatePtr cur, const xmlChar *mode, const xmlChar *modeURI); XSLTPUBFUN xsltTemplatePtr XSLTCALL xsltGetTemplate (xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStylesheetPtr style); XSLTPUBFUN void XSLTCALL xsltFreeTemplateHashes (xsltStylesheetPtr style); XSLTPUBFUN void XSLTCALL xsltCleanupTemplates (xsltStylesheetPtr style); #if 0 int xsltMatchPattern (xsltTransformContextPtr ctxt, xmlNodePtr node, const xmlChar *pattern, xmlDocPtr ctxtdoc, xmlNodePtr ctxtnode); #endif #ifdef __cplusplus } #endif #endif /* __XML_XSLT_PATTERN_H__ */ PK! ,libxslt/__pycache__/__init__.cpython-311.pycnu[ idS)Nr/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib64/python3.11/site-packages/lxml/includes/libxslt/__init__.pyrsrPK!Gvlibxslt/functions.hnu[/* * Summary: interface for the XSLT functions not from XPath * Description: a set of extra functions coming from XSLT but not in XPath * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard and Bjorn Reese */ #ifndef __XML_XSLT_FUNCTIONS_H__ #define __XML_XSLT_FUNCTIONS_H__ #include #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /** * XSLT_REGISTER_FUNCTION_LOOKUP: * * Registering macro, not general purpose at all but used in different modules. */ #define XSLT_REGISTER_FUNCTION_LOOKUP(ctxt) \ xmlXPathRegisterFuncLookup((ctxt)->xpathCtxt, \ xsltXPathFunctionLookup, \ (void *)(ctxt->xpathCtxt)); XSLTPUBFUN xmlXPathFunction XSLTCALL xsltXPathFunctionLookup (void *vctxt, const xmlChar *name, const xmlChar *ns_uri); /* * Interfaces for the functions implementations. */ XSLTPUBFUN void XSLTCALL xsltDocumentFunction (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltKeyFunction (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltUnparsedEntityURIFunction (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltFormatNumberFunction (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltGenerateIdFunction (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltSystemPropertyFunction (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltElementAvailableFunction (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltFunctionAvailableFunction (xmlXPathParserContextPtr ctxt, int nargs); /* * And the registration */ XSLTPUBFUN void XSLTCALL xsltRegisterAllFunctions (xmlXPathContextPtr ctxt); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_FUNCTIONS_H__ */ PK!Պ.?  libxslt/xsltlocale.hnu[/* * Summary: Locale handling * Description: Interfaces for locale handling. Needed for language dependent * sorting. * * Copy: See Copyright for the status of this software. * * Author: Nick Wellnhofer */ #ifndef __XML_XSLTLOCALE_H__ #define __XML_XSLTLOCALE_H__ #include #include "xsltexports.h" #ifdef HAVE_STRXFRM_L /* * XSLT_LOCALE_POSIX: * Macro indicating to use POSIX locale extensions */ #define XSLT_LOCALE_POSIX #ifdef HAVE_LOCALE_H #include #endif #ifdef HAVE_XLOCALE_H #include #endif typedef locale_t xsltLocale; typedef xmlChar xsltLocaleChar; #elif defined(_WIN32) && !defined(__CYGWIN__) /* * XSLT_LOCALE_WINAPI: * Macro indicating to use WinAPI for extended locale support */ #define XSLT_LOCALE_WINAPI #include #include typedef LCID xsltLocale; typedef wchar_t xsltLocaleChar; #else /* * XSLT_LOCALE_NONE: * Macro indicating that there's no extended locale support */ #define XSLT_LOCALE_NONE typedef void *xsltLocale; typedef xmlChar xsltLocaleChar; #endif XSLTPUBFUN xsltLocale XSLTCALL xsltNewLocale (const xmlChar *langName); XSLTPUBFUN void XSLTCALL xsltFreeLocale (xsltLocale locale); XSLTPUBFUN xsltLocaleChar * XSLTCALL xsltStrxfrm (xsltLocale locale, const xmlChar *string); XSLTPUBFUN int XSLTCALL xsltLocaleStrcmp (xsltLocale locale, const xsltLocaleChar *str1, const xsltLocaleChar *str2); XSLTPUBFUN void XSLTCALL xsltFreeLocales (void); #endif /* __XML_XSLTLOCALE_H__ */ PK!Hlibxslt/xslt.hnu[/* * Summary: Interfaces, constants and types related to the XSLT engine * Description: Interfaces, constants and types related to the XSLT engine * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_H__ #define __XML_XSLT_H__ #include #include "xsltexports.h" #ifdef __cplusplus extern "C" { #endif /** * XSLT_DEFAULT_VERSION: * * The default version of XSLT supported. */ #define XSLT_DEFAULT_VERSION "1.0" /** * XSLT_DEFAULT_VENDOR: * * The XSLT "vendor" string for this processor. */ #define XSLT_DEFAULT_VENDOR "libxslt" /** * XSLT_DEFAULT_URL: * * The XSLT "vendor" URL for this processor. */ #define XSLT_DEFAULT_URL "http://xmlsoft.org/XSLT/" /** * XSLT_NAMESPACE: * * The XSLT specification namespace. */ #define XSLT_NAMESPACE ((const xmlChar *)"http://www.w3.org/1999/XSL/Transform") /** * XSLT_PARSE_OPTIONS: * * The set of options to pass to an xmlReadxxx when loading files for * XSLT consumption. */ #define XSLT_PARSE_OPTIONS \ XML_PARSE_NOENT | XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR | XML_PARSE_NOCDATA /** * xsltMaxDepth: * * This value is used to detect templates loops. */ XSLTPUBVAR int xsltMaxDepth; /** * * xsltMaxVars: * * * * This value is used to detect templates loops. * */ XSLTPUBVAR int xsltMaxVars; /** * xsltEngineVersion: * * The version string for libxslt. */ XSLTPUBVAR const char *xsltEngineVersion; /** * xsltLibxsltVersion: * * The version of libxslt compiled. */ XSLTPUBVAR const int xsltLibxsltVersion; /** * xsltLibxmlVersion: * * The version of libxml libxslt was compiled against. */ XSLTPUBVAR const int xsltLibxmlVersion; /* * Global initialization function. */ XSLTPUBFUN void XSLTCALL xsltInit (void); /* * Global cleanup function. */ XSLTPUBFUN void XSLTCALL xsltCleanupGlobals (void); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_H__ */ PK!_Dlibxslt/templates.hnu[/* * Summary: interface for the template processing * Description: This set of routine encapsulates XPath calls * and Attribute Value Templates evaluation. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_TEMPLATES_H__ #define __XML_XSLT_TEMPLATES_H__ #include #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif XSLTPUBFUN int XSLTCALL xsltEvalXPathPredicate (xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, xmlNsPtr *nsList, int nsNr); XSLTPUBFUN xmlChar * XSLTCALL xsltEvalTemplateString (xsltTransformContextPtr ctxt, xmlNodePtr contextNode, xmlNodePtr inst); XSLTPUBFUN xmlChar * XSLTCALL xsltEvalAttrValueTemplate (xsltTransformContextPtr ctxt, xmlNodePtr node, const xmlChar *name, const xmlChar *ns); XSLTPUBFUN const xmlChar * XSLTCALL xsltEvalStaticAttrValueTemplate (xsltStylesheetPtr style, xmlNodePtr node, const xmlChar *name, const xmlChar *ns, int *found); /* TODO: this is obviously broken ... the namespaces should be passed too ! */ XSLTPUBFUN xmlChar * XSLTCALL xsltEvalXPathString (xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp); XSLTPUBFUN xmlChar * XSLTCALL xsltEvalXPathStringNs (xsltTransformContextPtr ctxt, xmlXPathCompExprPtr comp, int nsNr, xmlNsPtr *nsList); XSLTPUBFUN xmlNodePtr * XSLTCALL xsltTemplateProcess (xsltTransformContextPtr ctxt, xmlNodePtr node); XSLTPUBFUN xmlAttrPtr XSLTCALL xsltAttrListTemplateProcess (xsltTransformContextPtr ctxt, xmlNodePtr target, xmlAttrPtr cur); XSLTPUBFUN xmlAttrPtr XSLTCALL xsltAttrTemplateProcess (xsltTransformContextPtr ctxt, xmlNodePtr target, xmlAttrPtr attr); XSLTPUBFUN xmlChar * XSLTCALL xsltAttrTemplateValueProcess (xsltTransformContextPtr ctxt, const xmlChar* attr); XSLTPUBFUN xmlChar * XSLTCALL xsltAttrTemplateValueProcessNode(xsltTransformContextPtr ctxt, const xmlChar* str, xmlNodePtr node); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_TEMPLATES_H__ */ PK!ҚC\ \ libxslt/security.hnu[/* * Summary: interface for the libxslt security framework * Description: the libxslt security framework allow to restrict * the access to new resources (file or URL) from * the stylesheet at runtime. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_SECURITY_H__ #define __XML_XSLT_SECURITY_H__ #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /** * xsltSecurityPref: * * structure to indicate the preferences for security in the XSLT * transformation. */ typedef struct _xsltSecurityPrefs xsltSecurityPrefs; typedef xsltSecurityPrefs *xsltSecurityPrefsPtr; /** * xsltSecurityOption: * * the set of option that can be configured */ typedef enum { XSLT_SECPREF_READ_FILE = 1, XSLT_SECPREF_WRITE_FILE, XSLT_SECPREF_CREATE_DIRECTORY, XSLT_SECPREF_READ_NETWORK, XSLT_SECPREF_WRITE_NETWORK } xsltSecurityOption; /** * xsltSecurityCheck: * * User provided function to check the value of a string like a file * path or an URL ... */ typedef int (*xsltSecurityCheck) (xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt, const char *value); /* * Module interfaces */ XSLTPUBFUN xsltSecurityPrefsPtr XSLTCALL xsltNewSecurityPrefs (void); XSLTPUBFUN void XSLTCALL xsltFreeSecurityPrefs (xsltSecurityPrefsPtr sec); XSLTPUBFUN int XSLTCALL xsltSetSecurityPrefs (xsltSecurityPrefsPtr sec, xsltSecurityOption option, xsltSecurityCheck func); XSLTPUBFUN xsltSecurityCheck XSLTCALL xsltGetSecurityPrefs (xsltSecurityPrefsPtr sec, xsltSecurityOption option); XSLTPUBFUN void XSLTCALL xsltSetDefaultSecurityPrefs (xsltSecurityPrefsPtr sec); XSLTPUBFUN xsltSecurityPrefsPtr XSLTCALL xsltGetDefaultSecurityPrefs (void); XSLTPUBFUN int XSLTCALL xsltSetCtxtSecurityPrefs (xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt); XSLTPUBFUN int XSLTCALL xsltSecurityAllow (xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt, const char *value); XSLTPUBFUN int XSLTCALL xsltSecurityForbid (xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt, const char *value); /* * internal interfaces */ XSLTPUBFUN int XSLTCALL xsltCheckWrite (xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt, const xmlChar *URL); XSLTPUBFUN int XSLTCALL xsltCheckRead (xsltSecurityPrefsPtr sec, xsltTransformContextPtr ctxt, const xmlChar *URL); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_SECURITY_H__ */ PK!揁&libxslt/namespaces.hnu[/* * Summary: interface for the XSLT namespace handling * Description: set of function easing the processing and generation * of namespace nodes in XSLT. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_NAMESPACES_H__ #define __XML_XSLT_NAMESPACES_H__ #include #include "xsltexports.h" #ifdef __cplusplus extern "C" { #endif /* * Used within nsAliases hashtable when the default namespace is required * but it's not been explicitly defined */ /** * UNDEFINED_DEFAULT_NS: * * Special value for undefined namespace, internal */ #define UNDEFINED_DEFAULT_NS (const xmlChar *) -1L XSLTPUBFUN void XSLTCALL xsltNamespaceAlias (xsltStylesheetPtr style, xmlNodePtr node); XSLTPUBFUN xmlNsPtr XSLTCALL xsltGetNamespace (xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns, xmlNodePtr out); XSLTPUBFUN xmlNsPtr XSLTCALL xsltGetPlainNamespace (xsltTransformContextPtr ctxt, xmlNodePtr cur, xmlNsPtr ns, xmlNodePtr out); XSLTPUBFUN xmlNsPtr XSLTCALL xsltGetSpecialNamespace (xsltTransformContextPtr ctxt, xmlNodePtr cur, const xmlChar *URI, const xmlChar *prefix, xmlNodePtr out); XSLTPUBFUN xmlNsPtr XSLTCALL xsltCopyNamespace (xsltTransformContextPtr ctxt, xmlNodePtr elem, xmlNsPtr ns); XSLTPUBFUN xmlNsPtr XSLTCALL xsltCopyNamespaceList (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNsPtr cur); XSLTPUBFUN void XSLTCALL xsltFreeNamespaceAliasHashes (xsltStylesheetPtr style); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_NAMESPACES_H__ */ PK!Nflibxslt/keys.hnu[/* * Summary: interface for the key matching used in key() and template matches. * Description: implementation of the key mechanims. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_KEY_H__ #define __XML_XSLT_KEY_H__ #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /** * NODE_IS_KEYED: * * check for bit 15 set */ #define NODE_IS_KEYED (1 >> 15) XSLTPUBFUN int XSLTCALL xsltAddKey (xsltStylesheetPtr style, const xmlChar *name, const xmlChar *nameURI, const xmlChar *match, const xmlChar *use, xmlNodePtr inst); XSLTPUBFUN xmlNodeSetPtr XSLTCALL xsltGetKey (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI, const xmlChar *value); XSLTPUBFUN void XSLTCALL xsltInitCtxtKeys (xsltTransformContextPtr ctxt, xsltDocumentPtr doc); XSLTPUBFUN void XSLTCALL xsltFreeKeys (xsltStylesheetPtr style); XSLTPUBFUN void XSLTCALL xsltFreeDocumentKeys (xsltDocumentPtr doc); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_H__ */ PK!Jhhlibxslt/extra.hnu[/* * Summary: interface for the non-standard features * Description: implement some extension outside the XSLT namespace * but not EXSLT with is in a different library. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_EXTRA_H__ #define __XML_XSLT_EXTRA_H__ #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /** * XSLT_LIBXSLT_NAMESPACE: * * This is the libxslt namespace for specific extensions. */ #define XSLT_LIBXSLT_NAMESPACE ((xmlChar *) "http://xmlsoft.org/XSLT/namespace") /** * XSLT_SAXON_NAMESPACE: * * This is Michael Kay's Saxon processor namespace for extensions. */ #define XSLT_SAXON_NAMESPACE ((xmlChar *) "http://icl.com/saxon") /** * XSLT_XT_NAMESPACE: * * This is James Clark's XT processor namespace for extensions. */ #define XSLT_XT_NAMESPACE ((xmlChar *) "http://www.jclark.com/xt") /** * XSLT_XALAN_NAMESPACE: * * This is the Apache project XALAN processor namespace for extensions. */ #define XSLT_XALAN_NAMESPACE ((xmlChar *) \ "org.apache.xalan.xslt.extensions.Redirect") XSLTPUBFUN void XSLTCALL xsltFunctionNodeSet (xmlXPathParserContextPtr ctxt, int nargs); XSLTPUBFUN void XSLTCALL xsltDebug (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltRegisterExtras (xsltTransformContextPtr ctxt); XSLTPUBFUN void XSLTCALL xsltRegisterAllExtras (void); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_EXTRA_H__ */ PK!s 00libxslt/imports.hnu[/* * Summary: interface for the XSLT import support * Description: macros and fuctions needed to implement and * access the import tree * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_IMPORTS_H__ #define __XML_XSLT_IMPORTS_H__ #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /** * XSLT_GET_IMPORT_PTR: * * A macro to import pointers from the stylesheet cascading order. */ #define XSLT_GET_IMPORT_PTR(res, style, name) { \ xsltStylesheetPtr st = style; \ res = NULL; \ while (st != NULL) { \ if (st->name != NULL) { res = st->name; break; } \ st = xsltNextImport(st); \ }} /** * XSLT_GET_IMPORT_INT: * * A macro to import intergers from the stylesheet cascading order. */ #define XSLT_GET_IMPORT_INT(res, style, name) { \ xsltStylesheetPtr st = style; \ res = -1; \ while (st != NULL) { \ if (st->name != -1) { res = st->name; break; } \ st = xsltNextImport(st); \ }} /* * Module interfaces */ XSLTPUBFUN int XSLTCALL xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur); XSLTPUBFUN int XSLTCALL xsltParseStylesheetInclude (xsltStylesheetPtr style, xmlNodePtr cur); XSLTPUBFUN xsltStylesheetPtr XSLTCALL xsltNextImport (xsltStylesheetPtr style); XSLTPUBFUN int XSLTCALL xsltNeedElemSpaceHandling(xsltTransformContextPtr ctxt); XSLTPUBFUN int XSLTCALL xsltFindElemSpaceHandling(xsltTransformContextPtr ctxt, xmlNodePtr node); XSLTPUBFUN xsltTemplatePtr XSLTCALL xsltFindTemplate (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *nameURI); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_IMPORTS_H__ */ PK!J{libxslt/extensions.hnu[/* * Summary: interface for the extension support * Description: This provide the API needed for simple and module * extension support. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_EXTENSION_H__ #define __XML_XSLT_EXTENSION_H__ #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /** * Extension Modules API. */ /** * xsltInitGlobals: * * Initialize the global variables for extensions * */ XSLTPUBFUN void XSLTCALL xsltInitGlobals (void); /** * xsltStyleExtInitFunction: * @ctxt: an XSLT stylesheet * @URI: the namespace URI for the extension * * A function called at initialization time of an XSLT extension module. * * Returns a pointer to the module specific data for this transformation. */ typedef void * (*xsltStyleExtInitFunction) (xsltStylesheetPtr style, const xmlChar *URI); /** * xsltStyleExtShutdownFunction: * @ctxt: an XSLT stylesheet * @URI: the namespace URI for the extension * @data: the data associated to this module * * A function called at shutdown time of an XSLT extension module. */ typedef void (*xsltStyleExtShutdownFunction) (xsltStylesheetPtr style, const xmlChar *URI, void *data); /** * xsltExtInitFunction: * @ctxt: an XSLT transformation context * @URI: the namespace URI for the extension * * A function called at initialization time of an XSLT extension module. * * Returns a pointer to the module specific data for this transformation. */ typedef void * (*xsltExtInitFunction) (xsltTransformContextPtr ctxt, const xmlChar *URI); /** * xsltExtShutdownFunction: * @ctxt: an XSLT transformation context * @URI: the namespace URI for the extension * @data: the data associated to this module * * A function called at shutdown time of an XSLT extension module. */ typedef void (*xsltExtShutdownFunction) (xsltTransformContextPtr ctxt, const xmlChar *URI, void *data); XSLTPUBFUN int XSLTCALL xsltRegisterExtModule (const xmlChar *URI, xsltExtInitFunction initFunc, xsltExtShutdownFunction shutdownFunc); XSLTPUBFUN int XSLTCALL xsltRegisterExtModuleFull (const xmlChar * URI, xsltExtInitFunction initFunc, xsltExtShutdownFunction shutdownFunc, xsltStyleExtInitFunction styleInitFunc, xsltStyleExtShutdownFunction styleShutdownFunc); XSLTPUBFUN int XSLTCALL xsltUnregisterExtModule (const xmlChar * URI); XSLTPUBFUN void * XSLTCALL xsltGetExtData (xsltTransformContextPtr ctxt, const xmlChar *URI); XSLTPUBFUN void * XSLTCALL xsltStyleGetExtData (xsltStylesheetPtr style, const xmlChar *URI); #ifdef XSLT_REFACTORED XSLTPUBFUN void * XSLTCALL xsltStyleStylesheetLevelGetExtData( xsltStylesheetPtr style, const xmlChar * URI); #endif XSLTPUBFUN void XSLTCALL xsltShutdownCtxtExts (xsltTransformContextPtr ctxt); XSLTPUBFUN void XSLTCALL xsltShutdownExts (xsltStylesheetPtr style); XSLTPUBFUN xsltTransformContextPtr XSLTCALL xsltXPathGetTransformContext (xmlXPathParserContextPtr ctxt); /* * extension functions */ XSLTPUBFUN int XSLTCALL xsltRegisterExtModuleFunction (const xmlChar *name, const xmlChar *URI, xmlXPathFunction function); XSLTPUBFUN xmlXPathFunction XSLTCALL xsltExtModuleFunctionLookup (const xmlChar *name, const xmlChar *URI); XSLTPUBFUN int XSLTCALL xsltUnregisterExtModuleFunction (const xmlChar *name, const xmlChar *URI); /* * extension elements */ typedef xsltElemPreCompPtr (*xsltPreComputeFunction) (xsltStylesheetPtr style, xmlNodePtr inst, xsltTransformFunction function); XSLTPUBFUN xsltElemPreCompPtr XSLTCALL xsltNewElemPreComp (xsltStylesheetPtr style, xmlNodePtr inst, xsltTransformFunction function); XSLTPUBFUN void XSLTCALL xsltInitElemPreComp (xsltElemPreCompPtr comp, xsltStylesheetPtr style, xmlNodePtr inst, xsltTransformFunction function, xsltElemPreCompDeallocator freeFunc); XSLTPUBFUN int XSLTCALL xsltRegisterExtModuleElement (const xmlChar *name, const xmlChar *URI, xsltPreComputeFunction precomp, xsltTransformFunction transform); XSLTPUBFUN xsltTransformFunction XSLTCALL xsltExtElementLookup (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI); XSLTPUBFUN xsltTransformFunction XSLTCALL xsltExtModuleElementLookup (const xmlChar *name, const xmlChar *URI); XSLTPUBFUN xsltPreComputeFunction XSLTCALL xsltExtModuleElementPreComputeLookup (const xmlChar *name, const xmlChar *URI); XSLTPUBFUN int XSLTCALL xsltUnregisterExtModuleElement (const xmlChar *name, const xmlChar *URI); /* * top-level elements */ typedef void (*xsltTopLevelFunction) (xsltStylesheetPtr style, xmlNodePtr inst); XSLTPUBFUN int XSLTCALL xsltRegisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI, xsltTopLevelFunction function); XSLTPUBFUN xsltTopLevelFunction XSLTCALL xsltExtModuleTopLevelLookup (const xmlChar *name, const xmlChar *URI); XSLTPUBFUN int XSLTCALL xsltUnregisterExtModuleTopLevel (const xmlChar *name, const xmlChar *URI); /* These 2 functions are deprecated for use within modules. */ XSLTPUBFUN int XSLTCALL xsltRegisterExtFunction (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI, xmlXPathFunction function); XSLTPUBFUN int XSLTCALL xsltRegisterExtElement (xsltTransformContextPtr ctxt, const xmlChar *name, const xmlChar *URI, xsltTransformFunction function); /* * Extension Prefix handling API. * Those are used by the XSLT (pre)processor. */ XSLTPUBFUN int XSLTCALL xsltRegisterExtPrefix (xsltStylesheetPtr style, const xmlChar *prefix, const xmlChar *URI); XSLTPUBFUN int XSLTCALL xsltCheckExtPrefix (xsltStylesheetPtr style, const xmlChar *URI); XSLTPUBFUN int XSLTCALL xsltCheckExtURI (xsltStylesheetPtr style, const xmlChar *URI); XSLTPUBFUN int XSLTCALL xsltInitCtxtExts (xsltTransformContextPtr ctxt); XSLTPUBFUN void XSLTCALL xsltFreeCtxtExts (xsltTransformContextPtr ctxt); XSLTPUBFUN void XSLTCALL xsltFreeExts (xsltStylesheetPtr style); XSLTPUBFUN xsltElemPreCompPtr XSLTCALL xsltPreComputeExtModuleElement (xsltStylesheetPtr style, xmlNodePtr inst); /* * Extension Infos access. * Used by exslt initialisation */ XSLTPUBFUN xmlHashTablePtr XSLTCALL xsltGetExtInfo (xsltStylesheetPtr style, const xmlChar *URI); /** * Test of the extension module API */ XSLTPUBFUN void XSLTCALL xsltRegisterTestModule (void); XSLTPUBFUN void XSLTCALL xsltDebugDumpExtensions (FILE * output); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_EXTENSION_H__ */ PK!>libxslt/attributes.hnu[/* * Summary: interface for the XSLT attribute handling * Description: this module handles the specificities of attribute * and attribute groups processing. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_ATTRIBUTES_H__ #define __XML_XSLT_ATTRIBUTES_H__ #include #include "xsltexports.h" #ifdef __cplusplus extern "C" { #endif XSLTPUBFUN void XSLTCALL xsltParseStylesheetAttributeSet (xsltStylesheetPtr style, xmlNodePtr cur); XSLTPUBFUN void XSLTCALL xsltFreeAttributeSetsHashes (xsltStylesheetPtr style); XSLTPUBFUN void XSLTCALL xsltApplyAttributeSet (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, const xmlChar *attributes); XSLTPUBFUN void XSLTCALL xsltResolveStylesheetAttributeSet(xsltStylesheetPtr style); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_ATTRIBUTES_H__ */ PK!ۀlibxslt/preproc.hnu[/* * Summary: precomputing stylesheets * Description: this is the compilation phase, where most of the * stylesheet is "compiled" into faster to use data. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_PRECOMP_H__ #define __XML_XSLT_PRECOMP_H__ #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /* * Interfaces */ XSLTPUBVAR const xmlChar *xsltExtMarker; XSLTPUBFUN xsltElemPreCompPtr XSLTCALL xsltDocumentComp (xsltStylesheetPtr style, xmlNodePtr inst, xsltTransformFunction function); XSLTPUBFUN void XSLTCALL xsltStylePreCompute (xsltStylesheetPtr style, xmlNodePtr inst); XSLTPUBFUN void XSLTCALL xsltFreeStylePreComps (xsltStylesheetPtr style); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_PRECOMP_H__ */ PK!~libxslt/transform.hnu[/* * Summary: the XSLT engine transformation part. * Description: This module implements the bulk of the actual * transformation processing. Most of the xsl: element * constructs are implemented in this module. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLT_TRANSFORM_H__ #define __XML_XSLT_TRANSFORM_H__ #include #include #include "xsltexports.h" #include #ifdef __cplusplus extern "C" { #endif /** * XInclude default processing. */ XSLTPUBFUN void XSLTCALL xsltSetXIncludeDefault (int xinclude); XSLTPUBFUN int XSLTCALL xsltGetXIncludeDefault (void); /** * Export context to users. */ XSLTPUBFUN xsltTransformContextPtr XSLTCALL xsltNewTransformContext (xsltStylesheetPtr style, xmlDocPtr doc); XSLTPUBFUN void XSLTCALL xsltFreeTransformContext(xsltTransformContextPtr ctxt); XSLTPUBFUN xmlDocPtr XSLTCALL xsltApplyStylesheetUser (xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, FILE * profile, xsltTransformContextPtr userCtxt); XSLTPUBFUN void XSLTCALL xsltProcessOneNode (xsltTransformContextPtr ctxt, xmlNodePtr node, xsltStackElemPtr params); /** * Private Interfaces. */ XSLTPUBFUN void XSLTCALL xsltApplyStripSpaces (xsltTransformContextPtr ctxt, xmlNodePtr node); XSLTPUBFUN xmlDocPtr XSLTCALL xsltApplyStylesheet (xsltStylesheetPtr style, xmlDocPtr doc, const char **params); XSLTPUBFUN xmlDocPtr XSLTCALL xsltProfileStylesheet (xsltStylesheetPtr style, xmlDocPtr doc, const char **params, FILE * output); XSLTPUBFUN int XSLTCALL xsltRunStylesheet (xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf); XSLTPUBFUN int XSLTCALL xsltRunStylesheetUser (xsltStylesheetPtr style, xmlDocPtr doc, const char **params, const char *output, xmlSAXHandlerPtr SAX, xmlOutputBufferPtr IObuf, FILE * profile, xsltTransformContextPtr userCtxt); XSLTPUBFUN void XSLTCALL xsltApplyOneTemplate (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr list, xsltTemplatePtr templ, xsltStackElemPtr params); XSLTPUBFUN void XSLTCALL xsltDocumentElem (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltSort (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltCopy (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltText (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltElement (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltComment (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltAttribute (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltProcessingInstruction(xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltCopyOf (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltValueOf (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltNumber (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltApplyImports (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltCallTemplate (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltApplyTemplates (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltChoose (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltIf (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltForEach (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp); XSLTPUBFUN void XSLTCALL xsltRegisterAllElement (xsltTransformContextPtr ctxt); XSLTPUBFUN xmlNodePtr XSLTCALL xsltCopyTextString (xsltTransformContextPtr ctxt, xmlNodePtr target, const xmlChar *string, int noescape); /* Following 2 functions needed for libexslt/functions.c */ XSLTPUBFUN void XSLTCALL xsltLocalVariablePop (xsltTransformContextPtr ctxt, int limitNr, int level); XSLTPUBFUN int XSLTCALL xsltLocalVariablePush (xsltTransformContextPtr ctxt, xsltStackElemPtr variable, int level); /* * Hook for the debugger if activated. */ XSLTPUBFUN void XSLTCALL xslHandleDebugger (xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt); #ifdef __cplusplus } #endif #endif /* __XML_XSLT_TRANSFORM_H__ */ PK!libxslt/__init__.pynu[PK!*do o libxslt/xsltexports.hnu[/* * Summary: macros for marking symbols as exportable/importable. * Description: macros for marking symbols as exportable/importable. * * Copy: See Copyright for the status of this software. * * Author: Igor Zlatkovic */ #ifndef __XSLT_EXPORTS_H__ #define __XSLT_EXPORTS_H__ /** * XSLTPUBFUN: * XSLTPUBFUN, XSLTPUBVAR, XSLTCALL * * Macros which declare an exportable function, an exportable variable and * the calling convention used for functions. * * Please use an extra block for every platform/compiler combination when * modifying this, rather than overlong #ifdef lines. This helps * readability as well as the fact that different compilers on the same * platform might need different definitions. */ /** * XSLTPUBFUN: * * Macros which declare an exportable function */ #define XSLTPUBFUN /** * XSLTPUBVAR: * * Macros which declare an exportable variable */ #define XSLTPUBVAR extern /** * XSLTCALL: * * Macros which declare the called convention for exported functions */ #define XSLTCALL /** DOC_DISABLE */ /* Windows platform with MS compiler */ #if defined(_WIN32) && defined(_MSC_VER) #undef XSLTPUBFUN #undef XSLTPUBVAR #undef XSLTCALL #if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC) #define XSLTPUBFUN __declspec(dllexport) #define XSLTPUBVAR __declspec(dllexport) #else #define XSLTPUBFUN #if !defined(LIBXSLT_STATIC) #define XSLTPUBVAR __declspec(dllimport) extern #else #define XSLTPUBVAR extern #endif #endif #define XSLTCALL __cdecl #if !defined _REENTRANT #define _REENTRANT #endif #endif /* Windows platform with Borland compiler */ #if defined(_WIN32) && defined(__BORLANDC__) #undef XSLTPUBFUN #undef XSLTPUBVAR #undef XSLTCALL #if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC) #define XSLTPUBFUN __declspec(dllexport) #define XSLTPUBVAR __declspec(dllexport) extern #else #define XSLTPUBFUN #if !defined(LIBXSLT_STATIC) #define XSLTPUBVAR __declspec(dllimport) extern #else #define XSLTPUBVAR extern #endif #endif #define XSLTCALL __cdecl #if !defined _REENTRANT #define _REENTRANT #endif #endif /* Windows platform with GNU compiler (Mingw) */ #if defined(_WIN32) && defined(__MINGW32__) #undef XSLTPUBFUN #undef XSLTPUBVAR #undef XSLTCALL /* #if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC) */ #if !defined(LIBXSLT_STATIC) #define XSLTPUBFUN __declspec(dllexport) #define XSLTPUBVAR __declspec(dllexport) extern #else #define XSLTPUBFUN #if !defined(LIBXSLT_STATIC) #define XSLTPUBVAR __declspec(dllimport) extern #else #define XSLTPUBVAR extern #endif #endif #define XSLTCALL __cdecl #if !defined _REENTRANT #define _REENTRANT #endif #endif /* Cygwin platform (does not define _WIN32), GNU compiler */ #if defined(__CYGWIN__) #undef XSLTPUBFUN #undef XSLTPUBVAR #undef XSLTCALL #if defined(IN_LIBXSLT) && !defined(LIBXSLT_STATIC) #define XSLTPUBFUN __declspec(dllexport) #define XSLTPUBVAR __declspec(dllexport) #else #define XSLTPUBFUN #if !defined(LIBXSLT_STATIC) #define XSLTPUBVAR __declspec(dllimport) extern #else #define XSLTPUBVAR extern #endif #endif #define XSLTCALL __cdecl #endif /* Compatibility */ #if !defined(LIBXSLT_PUBLIC) #define LIBXSLT_PUBLIC XSLTPUBVAR #endif #endif /* __XSLT_EXPORTS_H__ */ PK!!j j libxslt/xsltutils.hnu[/* * Summary: set of utilities for the XSLT engine * Description: interfaces for the utilities module of the XSLT engine. * things like message handling, profiling, and other * generally useful routines. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLTUTILS_H__ #define __XML_XSLTUTILS_H__ #include #ifdef HAVE_STDARG_H #include #endif #include #include #include #include "xsltexports.h" #include "xsltInternals.h" #ifdef __cplusplus extern "C" { #endif /** * XSLT_TODO: * * Macro to flag unimplemented blocks. */ #define XSLT_TODO \ xsltGenericError(xsltGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__); /** * XSLT_STRANGE: * * Macro to flag that a problem was detected internally. */ #define XSLT_STRANGE \ xsltGenericError(xsltGenericErrorContext, \ "Internal error at %s:%d\n", \ __FILE__, __LINE__); /** * IS_XSLT_ELEM: * * Checks that the element pertains to XSLT namespace. */ #define IS_XSLT_ELEM(n) \ (((n) != NULL) && ((n)->type == XML_ELEMENT_NODE) && \ ((n)->ns != NULL) && (xmlStrEqual((n)->ns->href, XSLT_NAMESPACE))) /** * IS_XSLT_NAME: * * Checks the value of an element in XSLT namespace. */ #define IS_XSLT_NAME(n, val) \ (xmlStrEqual((n)->name, (const xmlChar *) (val))) /** * IS_XSLT_REAL_NODE: * * Check that a node is a 'real' one: document, element, text or attribute. */ #define IS_XSLT_REAL_NODE(n) \ (((n) != NULL) && \ (((n)->type == XML_ELEMENT_NODE) || \ ((n)->type == XML_TEXT_NODE) || \ ((n)->type == XML_CDATA_SECTION_NODE) || \ ((n)->type == XML_ATTRIBUTE_NODE) || \ ((n)->type == XML_DOCUMENT_NODE) || \ ((n)->type == XML_HTML_DOCUMENT_NODE) || \ ((n)->type == XML_COMMENT_NODE) || \ ((n)->type == XML_PI_NODE))) /* * Our own version of namespaced attributes lookup. */ XSLTPUBFUN xmlChar * XSLTCALL xsltGetNsProp (xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace); XSLTPUBFUN const xmlChar * XSLTCALL xsltGetCNsProp (xsltStylesheetPtr style, xmlNodePtr node, const xmlChar *name, const xmlChar *nameSpace); XSLTPUBFUN int XSLTCALL xsltGetUTF8Char (const unsigned char *utf, int *len); /* * XSLT Debug Tracing Tracing Types */ typedef enum { XSLT_TRACE_ALL = -1, XSLT_TRACE_NONE = 0, XSLT_TRACE_COPY_TEXT = 1<<0, XSLT_TRACE_PROCESS_NODE = 1<<1, XSLT_TRACE_APPLY_TEMPLATE = 1<<2, XSLT_TRACE_COPY = 1<<3, XSLT_TRACE_COMMENT = 1<<4, XSLT_TRACE_PI = 1<<5, XSLT_TRACE_COPY_OF = 1<<6, XSLT_TRACE_VALUE_OF = 1<<7, XSLT_TRACE_CALL_TEMPLATE = 1<<8, XSLT_TRACE_APPLY_TEMPLATES = 1<<9, XSLT_TRACE_CHOOSE = 1<<10, XSLT_TRACE_IF = 1<<11, XSLT_TRACE_FOR_EACH = 1<<12, XSLT_TRACE_STRIP_SPACES = 1<<13, XSLT_TRACE_TEMPLATES = 1<<14, XSLT_TRACE_KEYS = 1<<15, XSLT_TRACE_VARIABLES = 1<<16 } xsltDebugTraceCodes; /** * XSLT_TRACE: * * Control the type of xsl debugtrace messages emitted. */ #define XSLT_TRACE(ctxt,code,call) \ if (ctxt->traceCode && (*(ctxt->traceCode) & code)) \ call XSLTPUBFUN void XSLTCALL xsltDebugSetDefaultTrace(xsltDebugTraceCodes val); XSLTPUBFUN xsltDebugTraceCodes XSLTCALL xsltDebugGetDefaultTrace(void); /* * XSLT specific error and debug reporting functions. */ XSLTPUBVAR xmlGenericErrorFunc xsltGenericError; XSLTPUBVAR void *xsltGenericErrorContext; XSLTPUBVAR xmlGenericErrorFunc xsltGenericDebug; XSLTPUBVAR void *xsltGenericDebugContext; XSLTPUBFUN void XSLTCALL xsltPrintErrorContext (xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node); XSLTPUBFUN void XSLTCALL xsltMessage (xsltTransformContextPtr ctxt, xmlNodePtr node, xmlNodePtr inst); XSLTPUBFUN void XSLTCALL xsltSetGenericErrorFunc (void *ctx, xmlGenericErrorFunc handler); XSLTPUBFUN void XSLTCALL xsltSetGenericDebugFunc (void *ctx, xmlGenericErrorFunc handler); XSLTPUBFUN void XSLTCALL xsltSetTransformErrorFunc (xsltTransformContextPtr ctxt, void *ctx, xmlGenericErrorFunc handler); XSLTPUBFUN void XSLTCALL xsltTransformError (xsltTransformContextPtr ctxt, xsltStylesheetPtr style, xmlNodePtr node, const char *msg, ...) LIBXSLT_ATTR_FORMAT(4,5); XSLTPUBFUN int XSLTCALL xsltSetCtxtParseOptions (xsltTransformContextPtr ctxt, int options); /* * Sorting. */ XSLTPUBFUN void XSLTCALL xsltDocumentSortFunction (xmlNodeSetPtr list); XSLTPUBFUN void XSLTCALL xsltSetSortFunc (xsltSortFunc handler); XSLTPUBFUN void XSLTCALL xsltSetCtxtSortFunc (xsltTransformContextPtr ctxt, xsltSortFunc handler); XSLTPUBFUN void XSLTCALL xsltDefaultSortFunction (xsltTransformContextPtr ctxt, xmlNodePtr *sorts, int nbsorts); XSLTPUBFUN void XSLTCALL xsltDoSortFunction (xsltTransformContextPtr ctxt, xmlNodePtr * sorts, int nbsorts); XSLTPUBFUN xmlXPathObjectPtr * XSLTCALL xsltComputeSortResult (xsltTransformContextPtr ctxt, xmlNodePtr sort); /* * QNames handling. */ XSLTPUBFUN const xmlChar * XSLTCALL xsltSplitQName (xmlDictPtr dict, const xmlChar *name, const xmlChar **prefix); XSLTPUBFUN const xmlChar * XSLTCALL xsltGetQNameURI (xmlNodePtr node, xmlChar **name); XSLTPUBFUN const xmlChar * XSLTCALL xsltGetQNameURI2 (xsltStylesheetPtr style, xmlNodePtr node, const xmlChar **name); /* * Output, reuse libxml I/O buffers. */ XSLTPUBFUN int XSLTCALL xsltSaveResultTo (xmlOutputBufferPtr buf, xmlDocPtr result, xsltStylesheetPtr style); XSLTPUBFUN int XSLTCALL xsltSaveResultToFilename (const char *URI, xmlDocPtr result, xsltStylesheetPtr style, int compression); XSLTPUBFUN int XSLTCALL xsltSaveResultToFile (FILE *file, xmlDocPtr result, xsltStylesheetPtr style); XSLTPUBFUN int XSLTCALL xsltSaveResultToFd (int fd, xmlDocPtr result, xsltStylesheetPtr style); XSLTPUBFUN int XSLTCALL xsltSaveResultToString (xmlChar **doc_txt_ptr, int * doc_txt_len, xmlDocPtr result, xsltStylesheetPtr style); /* * XPath interface */ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL xsltXPathCompile (xsltStylesheetPtr style, const xmlChar *str); XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL xsltXPathCompileFlags (xsltStylesheetPtr style, const xmlChar *str, int flags); /* * Profiling. */ XSLTPUBFUN void XSLTCALL xsltSaveProfiling (xsltTransformContextPtr ctxt, FILE *output); XSLTPUBFUN xmlDocPtr XSLTCALL xsltGetProfileInformation (xsltTransformContextPtr ctxt); XSLTPUBFUN long XSLTCALL xsltTimestamp (void); XSLTPUBFUN void XSLTCALL xsltCalibrateAdjust (long delta); /** * XSLT_TIMESTAMP_TICS_PER_SEC: * * Sampling precision for profiling */ #define XSLT_TIMESTAMP_TICS_PER_SEC 100000l /* * Hooks for the debugger. */ typedef enum { XSLT_DEBUG_NONE = 0, /* no debugging allowed */ XSLT_DEBUG_INIT, XSLT_DEBUG_STEP, XSLT_DEBUG_STEPOUT, XSLT_DEBUG_NEXT, XSLT_DEBUG_STOP, XSLT_DEBUG_CONT, XSLT_DEBUG_RUN, XSLT_DEBUG_RUN_RESTART, XSLT_DEBUG_QUIT } xsltDebugStatusCodes; XSLTPUBVAR int xslDebugStatus; typedef void (*xsltHandleDebuggerCallback) (xmlNodePtr cur, xmlNodePtr node, xsltTemplatePtr templ, xsltTransformContextPtr ctxt); typedef int (*xsltAddCallCallback) (xsltTemplatePtr templ, xmlNodePtr source); typedef void (*xsltDropCallCallback) (void); XSLTPUBFUN void XSLTCALL xsltSetDebuggerStatus (int value); XSLTPUBFUN int XSLTCALL xsltGetDebuggerStatus (void); XSLTPUBFUN int XSLTCALL xsltSetDebuggerCallbacks (int no, void *block); XSLTPUBFUN int XSLTCALL xslAddCall (xsltTemplatePtr templ, xmlNodePtr source); XSLTPUBFUN void XSLTCALL xslDropCall (void); #ifdef __cplusplus } #endif #endif /* __XML_XSLTUTILS_H__ */ PK!{libxslt/xsltconfig.hnu[/* * Summary: compile-time version information for the XSLT engine * Description: compile-time version information for the XSLT engine * this module is autogenerated. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XSLTCONFIG_H__ #define __XML_XSLTCONFIG_H__ #ifdef __cplusplus extern "C" { #endif /** * LIBXSLT_DOTTED_VERSION: * * the version string like "1.2.3" */ #define LIBXSLT_DOTTED_VERSION "1.1.35" /** * LIBXSLT_VERSION: * * the version number: 1.2.3 value is 10203 */ #define LIBXSLT_VERSION 10135 /** * LIBXSLT_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ #define LIBXSLT_VERSION_STRING "10135" /** * LIBXSLT_VERSION_EXTRA: * * extra version information, used to show a CVS compilation */ #define LIBXSLT_VERSION_EXTRA "" /** * WITH_XSLT_DEBUG: * * Activate the compilation of the debug reporting. Speed penalty * is insignifiant and being able to run xsltpoc -v is useful. On * by default unless --without-debug is passed to configure */ #if 1 #define WITH_XSLT_DEBUG #endif #if 0 /** * DEBUG_MEMORY: * * should be activated only when debugging libxslt. It replaces the * allocator with a collect and debug shell to the libc allocator. * Use configure --with-mem-debug to activate it on both library */ #define DEBUG_MEMORY /** * DEBUG_MEMORY_LOCATION: * * should be activated only when debugging libxslt. * DEBUG_MEMORY_LOCATION should be activated only when libxml has * been configured with --with-debug-mem too */ #define DEBUG_MEMORY_LOCATION #endif /** * XSLT_NEED_TRIO: * * should be activated if the existing libc library lacks some of the * string formatting function, in that case reuse the Trio ones already * compiled in the libxml2 library. */ #if 0 #define XSLT_NEED_TRIO #endif #ifdef __VMS #define HAVE_MATH_H 1 #define HAVE_SYS_STAT_H 1 #ifndef XSLT_NEED_TRIO #define XSLT_NEED_TRIO #endif #endif #ifdef XSLT_NEED_TRIO #define TRIO_REPLACE_STDIO #endif /** * WITH_XSLT_DEBUGGER: * * Activate the compilation of the debugger support. Speed penalty * is insignifiant. * On by default unless --without-debugger is passed to configure */ #if 1 #ifndef WITH_DEBUGGER #define WITH_DEBUGGER #endif #endif /** * WITH_PROFILER: * * Activate the compilation of the profiler. Speed penalty * is insignifiant. * On by default unless --without-profiler is passed to configure */ #if 1 #ifndef WITH_PROFILER #define WITH_PROFILER #endif #endif /** * WITH_MODULES: * * Whether module support is configured into libxslt * Note: no default module path for win32 platforms */ #if 0 #ifndef WITH_MODULES #define WITH_MODULES #endif #define LIBXSLT_DEFAULT_PLUGINS_PATH() "/tmp/pip-req-build-v5uo8qug/build/tmp/libxml2/lib/libxslt-plugins" #endif /** * ATTRIBUTE_UNUSED: * * This macro is used to flag unused function parameters to GCC */ #ifdef __GNUC__ #ifndef ATTRIBUTE_UNUSED #define ATTRIBUTE_UNUSED __attribute__((unused)) #endif #else #define ATTRIBUTE_UNUSED #endif /** * LIBXSLT_ATTR_FORMAT: * * This macro is used to indicate to GCC the parameters are printf-like */ #ifdef __GNUC__ #define LIBXSLT_ATTR_FORMAT(fmt,args) __attribute__((__format__(__printf__,fmt,args))) #else #define LIBXSLT_ATTR_FORMAT(fmt,args) #endif /** * LIBXSLT_PUBLIC: * * This macro is used to declare PUBLIC variables for Cygwin and for MSC on Windows */ #if !defined LIBXSLT_PUBLIC #if (defined(__CYGWIN__) || defined _MSC_VER) && !defined IN_LIBXSLT && !defined LIBXSLT_STATIC #define LIBXSLT_PUBLIC __declspec(dllimport) #else #define LIBXSLT_PUBLIC #endif #endif #ifdef __cplusplus } #endif #endif /* __XML_XSLTCONFIG_H__ */ PK!pYpextlibs/libcharset.hnu[/* Copyright (C) 2003 Free Software Foundation, Inc. This file is part of the GNU CHARSET Library. The GNU CHARSET Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The GNU CHARSET Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU CHARSET Library; see the file COPYING.LIB. If not, see . */ #ifndef _LIBCHARSET_H #define _LIBCHARSET_H #include #ifdef __cplusplus extern "C" { #endif /* Support for relocatable packages. */ /* Sets the original and the current installation prefix of the package. Relocation simply replaces a pathname starting with the original prefix by the corresponding pathname with the current prefix instead. Both prefixes should be directory names without trailing slash (i.e. use "" instead of "/"). */ extern void libcharset_set_relocation_prefix (const char *orig_prefix, const char *curr_prefix); #ifdef __cplusplus } #endif #endif /* _LIBCHARSET_H */ PK!E@,extlibs/__pycache__/__init__.cpython-311.pycnu[ idS)Nr/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib64/python3.11/site-packages/lxml/includes/extlibs/__init__.pyrsrPK!*M[+|+|extlibs/zlib.hnu[/* zlib.h -- interface of the 'zlib' general purpose compression library version 1.2.13, October 13th, 2022 Copyright (C) 1995-2022 Jean-loup Gailly and Mark Adler This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Jean-loup Gailly Mark Adler jloup@gzip.org madler@alumni.caltech.edu The data format used by the zlib library is described by RFCs (Request for Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). */ #ifndef ZLIB_H #define ZLIB_H #include "zconf.h" #ifdef __cplusplus extern "C" { #endif #define ZLIB_VERSION "1.2.13" #define ZLIB_VERNUM 0x12d0 #define ZLIB_VER_MAJOR 1 #define ZLIB_VER_MINOR 2 #define ZLIB_VER_REVISION 13 #define ZLIB_VER_SUBREVISION 0 /* The 'zlib' compression library provides in-memory compression and decompression functions, including integrity checks of the uncompressed data. This version of the library supports only one compression method (deflation) but other algorithms will be added later and will have the same stream interface. Compression can be done in a single step if the buffers are large enough, or can be done by repeated calls of the compression function. In the latter case, the application must provide more input and/or consume the output (providing more output space) before each call. The compressed data format used by default by the in-memory functions is the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped around a deflate stream, which is itself documented in RFC 1951. The library also supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. This library can optionally read and write gzip and raw deflate streams in memory as well. The zlib format was designed to be compact and fast for use in memory and on communications channels. The gzip format was designed for single- file compression on file systems, has a larger header than zlib to maintain directory information, and uses a different, slower check method than zlib. The library does not install any signal handler. The decoder checks the consistency of the compressed data, so the library should never crash even in the case of corrupted input. */ typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { z_const Bytef *next_in; /* next input byte */ uInt avail_in; /* number of bytes available at next_in */ uLong total_in; /* total number of input bytes read so far */ Bytef *next_out; /* next output byte will go here */ uInt avail_out; /* remaining free space at next_out */ uLong total_out; /* total number of bytes output so far */ z_const char *msg; /* last error message, NULL if no error */ struct internal_state FAR *state; /* not visible by applications */ alloc_func zalloc; /* used to allocate the internal state */ free_func zfree; /* used to free the internal state */ voidpf opaque; /* private data object passed to zalloc and zfree */ int data_type; /* best guess about the data type: binary or text for deflate, or the decoding state for inflate */ uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ uLong reserved; /* reserved for future use */ } z_stream; typedef z_stream FAR *z_streamp; /* gzip header information passed to and from zlib routines. See RFC 1952 for more details on the meanings of these fields. */ typedef struct gz_header_s { int text; /* true if compressed data believed to be text */ uLong time; /* modification time */ int xflags; /* extra flags (not used when writing a gzip file) */ int os; /* operating system */ Bytef *extra; /* pointer to extra field or Z_NULL if none */ uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ uInt extra_max; /* space at extra (only when reading header) */ Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ uInt name_max; /* space at name (only when reading header) */ Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ uInt comm_max; /* space at comment (only when reading header) */ int hcrc; /* true if there was or will be a header crc */ int done; /* true when done reading gzip header (not used when writing a gzip file) */ } gz_header; typedef gz_header FAR *gz_headerp; /* The application must update next_in and avail_in when avail_in has dropped to zero. It must update next_out and avail_out when avail_out has dropped to zero. The application must initialize zalloc, zfree and opaque before calling the init function. All other fields are set by the compression library and must not be updated by the application. The opaque value provided by the application will be passed as the first parameter for calls of zalloc and zfree. This can be useful for custom memory management. The compression library attaches no meaning to the opaque value. zalloc must return Z_NULL if there is not enough memory for the object. If zlib is used in a multi-threaded application, zalloc and zfree must be thread safe. In that case, zlib is thread-safe. When zalloc and zfree are Z_NULL on entry to the initialization function, they are set to internal routines that use the standard library functions malloc() and free(). On 16-bit systems, the functions zalloc and zfree must be able to allocate exactly 65536 bytes, but will not be required to allocate more than this if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers returned by zalloc for objects of exactly 65536 bytes *must* have their offset normalized to zero. The default allocation function provided by this library ensures this (see zutil.c). To reduce memory requirements and avoid any allocation of 64K objects, at the expense of compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). The fields total_in and total_out can be used for statistics or progress reports. After compression, total_in holds the total size of the uncompressed data and may be saved for use by the decompressor (particularly if the decompressor wants to decompress everything in a single step). */ /* constants */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* Allowed flush values; see deflate() and inflate() below for details */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* Return codes for the compression/decompression functions. Negative values * are errors, positive values are used for special but normal events. */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* compression levels */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* compression strategy; see deflateInit2() below for details */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ #define Z_UNKNOWN 2 /* Possible values of the data_type field for deflate() */ #define Z_DEFLATED 8 /* The deflate compression method (the only one supported in this version) */ #define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ #define zlib_version zlibVersion() /* for compatibility with versions < 1.0.2 */ /* basic functions */ ZEXTERN const char * ZEXPORT zlibVersion OF((void)); /* The application can compare zlibVersion and ZLIB_VERSION for consistency. If the first character differs, the library code actually used is not compatible with the zlib.h header file used by the application. This check is automatically made by deflateInit and inflateInit. */ /* ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); Initializes the internal stream state for compression. The fields zalloc, zfree and opaque must be initialized before by the caller. If zalloc and zfree are set to Z_NULL, deflateInit updates them to use default allocation functions. The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6). deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level, or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); /* deflate compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. deflate performs one or both of the following actions: - Compress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), next_in and avail_in are updated and processing will resume at this point for the next call of deflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. This action is forced if the parameter flush is non zero. Forcing flush frequently degrades the compression ratio, so this parameter should be set only when necessary. Some output may be provided even if flush is zero. Before the call of deflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating avail_in or avail_out accordingly; avail_out should never be zero before the call. The application can consume the compressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. See deflatePending(), which can be used if desired to determine whether or not there is more output in that case. Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to decide how much data to accumulate before producing output, in order to maximize compression. If the parameter flush is set to Z_SYNC_FLUSH, all pending output is flushed to the output buffer and the output is aligned on a byte boundary, so that the decompressor can get all input data available so far. (In particular avail_in is zero after the call if enough output space has been provided before the call.) Flushing may degrade compression for some compression algorithms and so it should be used only when necessary. This completes the current deflate block and follows it with an empty stored block that is three bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the output buffer, but the output is not aligned to a byte boundary. All of the input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. This completes the current deflate block and follows it with an empty fixed codes block that is 10 bits long. This assures that enough bytes are output in order for the decompressor to finish the block before the empty fixed codes block. If flush is set to Z_BLOCK, a deflate block is completed and emitted, as for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to seven bits of the current block are held to be written as the next byte after the next deflate block is completed. In this case, the decompressor may not be provided enough bits at this point in order to complete decompression of the data provided so far to the compressor. It may need to wait for the next block to be emitted. This is for advanced applications that need to control the emission of deflate blocks. If flush is set to Z_FULL_FLUSH, all output is flushed as with Z_SYNC_FLUSH, and the compression state is reset so that decompression can restart from this point if previous compressed data has been damaged or if random access is desired. Using Z_FULL_FLUSH too often can seriously degrade compression. If deflate returns with avail_out == 0, this function must be called again with the same value of the flush parameter and more output space (updated avail_out), until the flush is complete (deflate returns with non-zero avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that avail_out is greater than six to avoid repeated flush markers due to avail_out == 0 on return. If the parameter flush is set to Z_FINISH, pending input is processed, pending output is flushed and deflate returns with Z_STREAM_END if there was enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this function must be called again with Z_FINISH and more output space (updated avail_out) but no more input data, until it returns with Z_STREAM_END or an error. After deflate has returned Z_STREAM_END, the only possible operations on the stream are deflateReset or deflateEnd. Z_FINISH can be used in the first deflate call after deflateInit if all the compression is to be done in a single step. In order to complete in one call, avail_out must be at least the value returned by deflateBound (see below). Then deflate is guaranteed to return Z_STREAM_END. If not enough output space is provided, deflate will not return Z_STREAM_END, and it must be called again as described above. deflate() sets strm->adler to the Adler-32 checksum of all input read so far (that is, total_in bytes). If a gzip stream is being generated, then strm->adler will be the CRC-32 checksum of the input read so far. (See deflateInit2 below.) deflate() may update strm->data_type if it can make a good guess about the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is considered binary. This field is only for information purposes and does not affect the compression algorithm in any manner. deflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if all input has been consumed and all output has been produced (only when flush is set to Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example if next_in or next_out was Z_NULL or the state was inadvertently written over by the application), or Z_BUF_ERROR if no progress is possible (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and deflate() can be called again with more input and more output space to continue compressing. */ ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state was inconsistent, Z_DATA_ERROR if the stream was freed prematurely (some input or output was discarded). In the error case, msg may be set but then points to a static string (which must not be deallocated). */ /* ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); Initializes the internal stream state for decompression. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. In the current version of inflate, the provided input is not read or consumed. The allocation of a sliding window will be deferred to the first call of inflate (if the decompression does not complete on the first call). If zalloc and zfree are set to Z_NULL, inflateInit updates them to use default allocation functions. inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit does not perform any decompression. Actual decompression will be done by inflate(). So next_in, and avail_in, next_out, and avail_out are unused and unchanged. The current implementation of inflateInit() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); /* inflate decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full. It may introduce some output latency (reading input without producing any output) except when forced to flush. The detailed semantics are as follows. inflate performs one or both of the following actions: - Decompress more input starting at next_in and update next_in and avail_in accordingly. If not all input can be processed (because there is not enough room in the output buffer), then next_in and avail_in are updated accordingly, and processing will resume at this point for the next call of inflate(). - Generate more output starting at next_out and update next_out and avail_out accordingly. inflate() provides as much output as possible, until there is no more input data or no more space in the output buffer (see below about the flush parameter). Before the call of inflate(), the application should ensure that at least one of the actions is possible, by providing more input and/or consuming more output, and updating the next_* and avail_* values accordingly. If the caller of inflate() does not provide both available input and available output space, it is possible that there will be no progress made. The application can consume the uncompressed output when it wants, for example when the output buffer is full (avail_out == 0), or after each call of inflate(). If inflate returns Z_OK and with zero avail_out, it must be called again after making room in the output buffer because there might be more output pending. The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much output as possible to the output buffer. Z_BLOCK requests that inflate() stop if and when it gets to the next deflate block boundary. When decoding the zlib or gzip format, this will cause inflate() to return immediately after the header and before the first block. When doing a raw inflate, inflate() will go ahead and process the first block, and will return when it gets to the end of that block, or when it runs out of data. The Z_BLOCK option assists in appending to or combining deflate streams. To assist in this, on return inflate() always sets strm->data_type to the number of unused bits in the last byte taken from strm->next_in, plus 64 if inflate() is currently decoding the last block in the deflate stream, plus 128 if inflate() returned immediately after decoding an end-of-block code or decoding the complete header up to just before the first byte of the deflate stream. The end-of-block will not be indicated until all of the uncompressed data from that block has been written to strm->next_out. The number of unused bits may in general be greater than seven, except when bit 7 of data_type is set, in which case the number of unused bits will be less than eight. data_type is set as noted here every time inflate() returns for all flush options, and so can be used to determine the amount of currently consumed input in bits. The Z_TREES option behaves as Z_BLOCK does, but it also returns when the end of each deflate block header is reached, before any actual data in that block is decoded. This allows the caller to determine the length of the deflate block header for later use in random access within a deflate block. 256 is added to the value of strm->data_type when inflate() returns immediately after reaching the end of the deflate block header. inflate() should normally be called until it returns Z_STREAM_END or an error. However if all decompression is to be performed in a single step (a single call of inflate), the parameter flush should be set to Z_FINISH. In this case all pending input is processed and all pending output is flushed; avail_out must be large enough to hold all of the uncompressed data for the operation to complete. (The size of the uncompressed data may have been saved by the compressor for this purpose.) The use of Z_FINISH is not required to perform an inflation in one step. However it may be used to inform inflate that a faster approach can be used for the single inflate() call. Z_FINISH also informs inflate to not maintain a sliding window if the stream completes, which reduces inflate's memory footprint. If the stream does not complete, either because not all of the stream is provided or not enough output space is provided, then a sliding window will be allocated and inflate() can be called again to continue the operation as if Z_NO_FLUSH had been used. In this implementation, inflate() always flushes as much output as possible to the output buffer, and always uses the faster approach on the first call. So the effects of the flush parameter in this implementation are on the return value of inflate() as noted below, when inflate() returns early when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of memory for a sliding window when Z_FINISH is used. If a preset dictionary is needed after this call (see inflateSetDictionary below), inflate sets strm->adler to the Adler-32 checksum of the dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise it sets strm->adler to the Adler-32 checksum of all output produced so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described below. At the end of the stream, inflate() checks that its computed Adler-32 checksum is equal to that saved by the compressor and returns Z_STREAM_END only if the checksum is correct. inflate() can decompress and check either zlib-wrapped or gzip-wrapped deflate data. The header type is detected automatically, if requested when initializing with inflateInit2(). Any information contained in the gzip header is not retained unless inflateGetHeader() is used. When processing gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output produced so far. The CRC-32 is checked against the gzip trailer, as is the uncompressed length, modulo 2^32. inflate() returns Z_OK if some progress has been made (more input processed or more output produced), Z_STREAM_END if the end of the compressed data has been reached and all uncompressed output has been produced, Z_NEED_DICT if a preset dictionary is needed at this point, Z_DATA_ERROR if the input data was corrupted (input stream not conforming to the zlib format or incorrect check value, in which case strm->msg points to a string with a more specific error), Z_STREAM_ERROR if the stream structure was inconsistent (for example next_in or next_out was Z_NULL, or the state was inadvertently written over by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if no progress was possible or if there was not enough room in the output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and inflate() can be called again with more input and more output space to continue decompressing. If Z_DATA_ERROR is returned, the application may then call inflateSync() to look for a good compression block if a partial recovery of the data is to be attempted. */ ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); /* All dynamically allocated data structures for this stream are freed. This function discards any unprocessed input and does not flush any pending output. inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state was inconsistent. */ /* Advanced functions */ /* The following functions are needed only in some special applications. */ /* ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy)); This is another version of deflateInit with more compression options. The fields zalloc, zfree and opaque must be initialized before by the caller. The method parameter is the compression method. It must be Z_DEFLATED in this version of the library. The windowBits parameter is the base two logarithm of the window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression at the expense of memory usage. The default value is 15 if deflateInit is used instead. For the current implementation of deflate(), a windowBits value of 8 (a window size of 256 bytes) is not supported. As a result, a request for 8 will result in 9 (a 512-byte window). In that case, providing 8 to inflateInit2() will result in an error when the zlib header with 9 is checked against the initialization of inflate(). The remedy is to not use 8 with deflateInit2() with this initialization, or at least in that case use 9 with inflateInit2(). windowBits can also be -8..-15 for raw deflate. In this case, -windowBits determines the window size. deflate() will then generate raw deflate data with no zlib header or trailer, and will not compute a check value. windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple gzip header and trailer around the compressed data instead of a zlib wrapper. The gzip header will have no file name, no extra data, no comment, no modification time (set to zero), no header crc, and the operating system will be set to the appropriate value, if the operating system was determined at compile time. If a gzip stream is being written, strm->adler is a CRC-32 instead of an Adler-32. For raw deflate or gzip encoding, a request for a 256-byte window is rejected as invalid, since only the zlib header provides a means of transmitting the window size to the decompressor. The memLevel parameter specifies how much memory should be allocated for the internal compression state. memLevel=1 uses minimum memory but is slow and reduces compression ratio; memLevel=9 uses maximum memory for optimal speed. The default value is 8. See zconf.h for total memory usage as a function of windowBits and memLevel. The strategy parameter is used to tune the compression algorithm. Use the value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no string match), or Z_RLE to limit match distances to one (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the compression algorithm is tuned to compress them better. The effect of Z_FILTERED is to force more Huffman coding and less string matching; it is somewhat intermediate between Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set appropriately. Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications. deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible with the version assumed by the caller (ZLIB_VERSION). msg is set to null if there is no error message. deflateInit2 does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the compression dictionary from the given byte sequence without producing any compressed output. When using the zlib format, this function must be called immediately after deflateInit, deflateInit2 or deflateReset, and before any call of deflate. When doing raw deflate, this function must be called either before any call of deflate, or immediately after the completion of a deflate block, i.e. after all input has been consumed and all output has been delivered when using any of the flush options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The compressor and decompressor must use exactly the same dictionary (see inflateSetDictionary). The dictionary should consist of strings (byte sequences) that are likely to be encountered later in the data to be compressed, with the most commonly used strings preferably put towards the end of the dictionary. Using a dictionary is most useful when the data to be compressed is short and can be predicted with good accuracy; the data can then be compressed better than with the default empty dictionary. Depending on the size of the compression data structures selected by deflateInit or deflateInit2, a part of the dictionary may in effect be discarded, for example if the dictionary is larger than the window size provided in deflateInit or deflateInit2. Thus the strings most likely to be useful should be put at the end of the dictionary, not at the front. In addition, the current implementation of deflate will use at most the window size minus 262 bytes of the provided dictionary. Upon return of this function, strm->adler is set to the Adler-32 value of the dictionary; the decompressor may later use this value to determine which dictionary has been used by the compressor. (The Adler-32 value applies to the whole dictionary even if only a subset of the dictionary is actually used by the compressor.) If a raw deflate was requested, then the Adler-32 value is not computed and strm->adler is not set. deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent (for example if deflate has already been called for this stream or if not at a block boundary for raw deflate). deflateSetDictionary does not perform any compression: this will be done by deflate(). */ ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, Bytef *dictionary, uInt *dictLength)); /* Returns the sliding dictionary being maintained by deflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If deflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similarly, if dictLength is Z_NULL, then it is not set. deflateGetDictionary() may return a length less than the window size, even when more than the window size in input has been provided. It may return up to 258 bytes less in that case, due to how zlib's implementation of deflate manages the sliding window and lookahead for matches, where matches can be up to 258 bytes long. If the application needs the last window-size bytes of input, then that would need to be saved by the application outside of zlib. deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter. The streams that will be discarded should then be freed by calling deflateEnd. Note that deflateCopy duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory. deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); /* This function is equivalent to deflateEnd followed by deflateInit, but does not free and reallocate the internal compression state. The stream will leave the compression level and any other attributes that may have been set unchanged. deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy)); /* Dynamically update the compression level and compression strategy. The interpretation of level and strategy is as in deflateInit2(). This can be used to switch between compression and straight copy of the input data, or to switch to a different kind of input data requiring a different strategy. If the compression approach (which is a function of the level) or the strategy is changed, and if there have been any deflate() calls since the state was initialized or reset, then the input available so far is compressed with the old level and strategy using deflate(strm, Z_BLOCK). There are three approaches for the compression levels 0, 1..3, and 4..9 respectively. The new level and strategy will take effect at the next call of deflate(). If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does not have enough output space to complete, then the parameter change will not take effect. In this case, deflateParams() can be called again with the same parameters and more output space to try again. In order to assure a change in the parameters on the first try, the deflate stream should be flushed using deflate() with Z_BLOCK or other flush request until strm.avail_out is not zero, before calling deflateParams(). Then no more input data should be provided before the deflateParams() call. If this is done, the old level and strategy will be applied to the data compressed before deflateParams(), and the new level and strategy will be applied to the the data compressed after deflateParams(). deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if there was not enough output space to complete the compression of the available input data before a change in the strategy or approach. Note that in the case of a Z_BUF_ERROR, the parameters are not changed. A return value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be retried with more output space. */ ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain)); /* Fine tune deflate's internal compression parameters. This should only be used by someone who understands the algorithm used by zlib's deflate for searching for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out the last compressed bit for their specific input data. Read the deflate.c source code for the meaning of the max_lazy, good_length, nice_length, and max_chain parameters. deflateTune() can be called after deflateInit() or deflateInit2(), and returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. */ ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen)); /* deflateBound() returns an upper bound on the compressed size after deflation of sourceLen bytes. It must be called after deflateInit() or deflateInit2(), and after deflateSetHeader(), if used. This would be used to allocate an output buffer for deflation in a single pass, and so would be called before deflate(). If that first deflate() call is provided the sourceLen input bytes, an output buffer allocated to the size returned by deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed to return Z_STREAM_END. Note that it is possible for the compressed size to be larger than the value returned by deflateBound() if flush options other than Z_FINISH or Z_NO_FLUSH are used. */ ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, unsigned *pending, int *bits)); /* deflatePending() returns the number of bytes and bits of output that have been generated, but not yet provided in the available output. The bytes not provided would be due to the available output space having being consumed. The number of bits of output not provided are between 0 and 7, where they await more bits to join them in order to fill out a full byte. If pending or bits are Z_NULL, then those values are not set. deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value)); /* deflatePrime() inserts bits in the deflate output stream. The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it. As such, this function can only be used for raw deflate, and must be used before the first deflate() call after a deflateInit2() or deflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output. deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gz_headerp head)); /* deflateSetHeader() provides gzip header information for when a gzip stream is requested by deflateInit2(). deflateSetHeader() may be called after deflateInit2() or deflateReset() and before the first call of deflate(). The text, time, os, extra field, name, and comment information in the provided gz_header structure are written to the gzip header (xflag is ignored -- the extra flags are set according to the compression level). The caller must assure that, if not Z_NULL, name and comment are terminated with a zero byte, and that if extra is not Z_NULL, that extra_len bytes are available there. If hcrc is true, a gzip header crc is included. Note that the current versions of the command-line version of gzip (up through version 1.3.x) do not support header crc's, and will report that it is a "multi-part gzip file" and give up. If deflateSetHeader is not used, the default gzip header has text false, the time set to zero, and os set to 255, with no extra, name, or comment fields. The gzip header is returned to the default state by deflateReset(). deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits)); This is another version of inflateInit with an extra parameter. The fields next_in, avail_in, zalloc, zfree and opaque must be initialized before by the caller. The windowBits parameter is the base two logarithm of the maximum window size (the size of the history buffer). It should be in the range 8..15 for this version of the library. The default value is 15 if inflateInit is used instead. windowBits must be greater than or equal to the windowBits value provided to deflateInit2() while compressing, or it must be equal to 15 if deflateInit2() was not used. If a compressed stream with a larger window size is given as input, inflate() will return with the error code Z_DATA_ERROR instead of trying to allocate a larger window. windowBits can also be zero to request that inflate use the window size in the zlib header of the compressed stream. windowBits can also be -8..-15 for raw inflate. In this case, -windowBits determines the window size. inflate() will then process raw deflate data, not looking for a zlib or gzip header, not generating a check value, and not looking for any check values for comparison at the end of the stream. This is for use with other formats that use the deflate compressed data format such as zip. Those formats provide their own check values. If a custom format is developed using the raw deflate format for compressed data, it is recommended that a check value such as an Adler-32 or a CRC-32 be applied to the uncompressed data as is done in the zlib, gzip, and zip formats. For most applications, the zlib format should be used as is. Note that comments above on the use in deflateInit2() applies to the magnitude of windowBits. windowBits can also be greater than 15 for optional gzip decoding. Add 32 to windowBits to enable zlib and gzip decoding with automatic header detection, or add 16 to decode only the gzip format (the zlib format will return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see below), inflate() will *not* automatically decode concatenated gzip members. inflate() will return Z_STREAM_END at the end of the gzip member. The state would need to be reset to continue decoding a subsequent gzip member. This *must* be done if there is more data after a gzip member, in order for the decompression to be compliant with the gzip standard (RFC 1952). inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_VERSION_ERROR if the zlib library version is incompatible with the version assumed by the caller, or Z_STREAM_ERROR if the parameters are invalid, such as a null pointer to the structure. msg is set to null if there is no error message. inflateInit2 does not perform any decompression apart from possibly reading the zlib header if present: actual decompression will be done by inflate(). (So next_in and avail_in may be modified, but next_out and avail_out are unused and unchanged.) The current implementation of inflateInit2() does not process any header information -- that is deferred until inflate() is called. */ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength)); /* Initializes the decompression dictionary from the given uncompressed byte sequence. This function must be called immediately after a call of inflate, if that call returned Z_NEED_DICT. The dictionary chosen by the compressor can be determined from the Adler-32 value returned by that call of inflate. The compressor and decompressor must use exactly the same dictionary (see deflateSetDictionary). For raw inflate, this function can be called at any time to set the dictionary. If the provided dictionary is smaller than the window and there is already data in the window, then the provided dictionary will amend what's there. The application must insure that the dictionary that was used for compression is provided. inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the expected one (incorrect Adler-32 value). inflateSetDictionary does not perform any decompression: this will be done by subsequent calls of inflate(). */ ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, Bytef *dictionary, uInt *dictLength)); /* Returns the sliding dictionary being maintained by inflate. dictLength is set to the number of bytes in the dictionary, and that many bytes are copied to dictionary. dictionary must have enough space, where 32768 bytes is always enough. If inflateGetDictionary() is called with dictionary equal to Z_NULL, then only the dictionary length is returned, and nothing is copied. Similarly, if dictLength is Z_NULL, then it is not set. inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the stream state is inconsistent. */ ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); /* Skips invalid compressed data until a possible full flush point (see above for the description of deflate with Z_FULL_FLUSH) can be found, or until all available input is skipped. No output is provided. inflateSync searches for a 00 00 FF FF pattern in the compressed data. All full flush points have this pattern, but not all occurrences of this pattern are full flush points. inflateSync returns Z_OK if a possible full flush point has been found, Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the success case, the application may save the current current value of total_in which indicates where valid compressed data was found. In the error case, the application may repeatedly call inflateSync, providing more input each time, until success or end of the input data. */ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, z_streamp source)); /* Sets the destination stream as a complete copy of the source stream. This function can be useful when randomly accessing a large stream. The first pass through the stream can periodically record the inflate state, allowing restarting inflate at those points when randomly accessing the stream. inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc being Z_NULL). msg is left unchanged in both source and destination. */ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); /* This function is equivalent to inflateEnd followed by inflateInit, but does not free and reallocate the internal decompression state. The stream will keep attributes that may have been set by inflateInit2. inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL). */ ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, int windowBits)); /* This function is the same as inflateReset, but it also permits changing the wrap and window size requests. The windowBits parameter is interpreted the same as it is for inflateInit2. If the window size is changed, then the memory allocated for the window is freed, and the window will be reallocated by inflate() if needed. inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent (such as zalloc or state being Z_NULL), or if the windowBits parameter is invalid. */ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, int bits, int value)); /* This function inserts bits in the inflate input stream. The intent is that this function is used to start inflating at a bit position in the middle of a byte. The provided bits will be used before any bytes are used from next_in. This function should only be used with raw inflate, and should be used before the first inflate() call after inflateInit2() or inflateReset(). bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input. If bits is negative, then the input stream bit buffer is emptied. Then inflatePrime() can be called again to put bits in the buffer. This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes. inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); /* This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits. If the upper value is -1 and the lower value is zero, then inflate() is currently decoding information outside of a block. If the upper value is -1 and the lower value is non-zero, then inflate is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy. If the upper value is not -1, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code. A code is being processed if inflate is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data. inflateMark() is used to mark locations in the input data for random access, which may be at bit positions, and to note those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from avail_in and data_type as noted in the description for the Z_BLOCK flush parameter for inflate. inflateMark returns the value noted above, or -65536 if the provided source stream state was inconsistent. */ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, gz_headerp head)); /* inflateGetHeader() requests that gzip header information be stored in the provided gz_header structure. inflateGetHeader() may be called after inflateInit2() or inflateReset(), and before the first call of inflate(). As inflate() processes the gzip stream, head->done is zero until the header is completed, at which time head->done is set to one. If a zlib stream is being decoded, then head->done is set to -1 to indicate that there will be no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be used to force inflate() to return immediately after header processing is complete and before any actual data is decompressed. The text, time, xflags, and os fields are filled in with the gzip header contents. hcrc is set to true if there is a header CRC. (The header CRC was valid if done is set to one.) If extra is not Z_NULL, then extra_max contains the maximum number of bytes to write to extra. Once done is true, extra_len contains the actual extra field length, and extra contains the extra field, or that field truncated if extra_max is less than extra_len. If name is not Z_NULL, then up to name_max characters are written there, terminated with a zero unless the length is greater than name_max. If comment is not Z_NULL, then up to comm_max characters are written there, terminated with a zero unless the length is greater than comm_max. When any of extra, name, or comment are not Z_NULL and the respective field is not present in the header, then that field is set to Z_NULL to signal its absence. This allows the use of deflateSetHeader() with the returned structure to duplicate the header. However if those fields are set to allocated memory, then the application will need to save those pointers elsewhere so that they can be eventually freed. If inflateGetHeader is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present. inflateReset() will reset the process to discard the header information. The application would need to call inflateGetHeader() again to retrieve the header from the next gzip stream. inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source stream state was inconsistent. */ /* ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window)); Initialize the internal stream state for decompression using inflateBack() calls. The fields zalloc, zfree and opaque in strm must be initialized before the call. If zalloc and zfree are Z_NULL, then the default library- derived memory allocation routines are used. windowBits is the base two logarithm of the window size, in the range 8..15. window is a caller supplied buffer of that size. Except for special applications where it is assured that deflate was used with small window sizes, windowBits must be 15 and a 32K byte window must be supplied to be able to decompress general deflate streams. See inflateBack() for the usage of these routines. inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of the parameters are invalid, Z_MEM_ERROR if the internal state could not be allocated, or Z_VERSION_ERROR if the version of the library does not match the version of the header file. */ typedef unsigned (*in_func) OF((void FAR *, z_const unsigned char FAR * FAR *)); typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)); /* inflateBack() does a raw inflate with a single call using a call-back interface for input and output. This is potentially more efficient than inflate() for file i/o applications, in that it avoids copying between the output and the sliding window by simply making the window itself the output buffer. inflate() can be faster on modern CPUs when used with large buffers. inflateBack() trusts the application to not change the output buffer passed by the output function, at least until inflateBack() returns. inflateBackInit() must be called first to allocate the internal state and to initialize the state with the user-provided window buffer. inflateBack() may then be used multiple times to inflate a complete, raw deflate stream with each call. inflateBackEnd() is then called to free the allocated state. A raw deflate stream is one with no zlib or gzip header or trailer. This routine would normally be used in a utility that reads zip or gzip files and writes out uncompressed files. The utility would decode the header and process the trailer on its own, hence this routine expects only the raw deflate stream to decompress. This is different from the default behavior of inflate(), which expects a zlib header and trailer around the deflate stream. inflateBack() uses two subroutines supplied by the caller that are then called by inflateBack() for input and output. inflateBack() calls those routines until it reads a complete deflate stream and writes out all of the uncompressed data, or until it encounters an error. The function's parameters and return types are defined above in the in_func and out_func typedefs. inflateBack() will call in(in_desc, &buf) which should return the number of bytes of provided input, and a pointer to that input in buf. If there is no input available, in() must return zero -- buf is ignored in that case -- and inflateBack() will return a buffer error. inflateBack() will call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() should return zero on success, or non-zero on failure. If out() returns non-zero, inflateBack() will return with an error. Neither in() nor out() are permitted to change the contents of the window provided to inflateBackInit(), which is also the buffer that out() uses to write from. The length written by out() will be at most the window size. Any non-zero amount of input may be provided by in(). For convenience, inflateBack() can be provided input on the first call by setting strm->next_in and strm->avail_in. If that input is exhausted, then in() will be called. Therefore strm->next_in must be initialized before calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in must also be initialized, and then if strm->avail_in is not zero, input will initially be taken from strm->next_in[0 .. strm->avail_in - 1]. The in_desc and out_desc parameters of inflateBack() is passed as the first parameter of in() and out() respectively when they are called. These descriptors can be optionally used to pass any information that the caller- supplied in() and out() functions need to do their job. On return, inflateBack() will set strm->next_in and strm->avail_in to pass back any unused input that was provided by the last in() call. The return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR if in() or out() returned an error, Z_DATA_ERROR if there was a format error in the deflate stream (in which case strm->msg is set to indicate the nature of the error), or Z_STREAM_ERROR if the stream was not properly initialized. In the case of Z_BUF_ERROR, an input or output error can be distinguished using strm->next_in which will be Z_NULL only if in() returned an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning non-zero. (in() will always be called before out(), so strm->next_in is assured to be defined if out() returns non-zero.) Note that inflateBack() cannot return Z_OK. */ ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); /* All memory allocated by inflateBackInit() is freed. inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream state was inconsistent. */ ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); /* Return flags indicating compile-time options. Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: 1.0: size of uInt 3.2: size of uLong 5.4: size of voidpf (pointer) 7.6: size of z_off_t Compiler, assembler, and debug options: 8: ZLIB_DEBUG 9: ASMV or ASMINF -- use ASM code 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention 11: 0 (reserved) One-time table building (smaller code, but not thread-safe if true): 12: BUILDFIXED -- build static block decoding tables when needed 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed 14,15: 0 (reserved) Library content (indicates missing functionality): 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking deflate code when not needed) 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) 18-19: 0 (reserved) Operation variations (changes in library functionality): 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate 21: FASTEST -- deflate algorithm with only one, lowest compression level 22,23: 0 (reserved) The sprintf variant used by gzprintf (zero is best): 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! 26: 0 = returns value, 1 = void -- 1 means inferred string length returned Remainder: 27-31: 0 (reserved) */ #ifndef Z_SOLO /* utility functions */ /* The following utility functions are implemented on top of the basic stream-oriented functions. To simplify the interface, some default options are assumed (compression level and memory usage, standard memory allocation functions). The source code of these utility functions can be modified if you need special options. */ ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Compresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress() is equivalent to compress2() with a level parameter of Z_DEFAULT_COMPRESSION. compress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer. */ ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level)); /* Compresses the source buffer into the destination buffer. The level parameter has the same meaning as in deflateInit. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be at least the value returned by compressBound(sourceLen). Upon exit, destLen is the actual size of the compressed data. compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, Z_STREAM_ERROR if the level parameter is invalid. */ ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); /* compressBound() returns an upper bound on the compressed size after compress() or compress2() on sourceLen bytes. It would be used before a compress() or compress2() call to allocate the destination buffer. */ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)); /* Decompresses the source buffer into the destination buffer. sourceLen is the byte length of the source buffer. Upon entry, destLen is the total size of the destination buffer, which must be large enough to hold the entire uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.) Upon exit, destLen is the actual size of the uncompressed data. uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR if there was not enough room in the output buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In the case where there is not enough room, uncompress() will fill the output buffer with the uncompressed data up to that point. */ ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong *sourceLen)); /* Same as uncompress, except that sourceLen is a pointer, where the length of the source is *sourceLen. On return, *sourceLen is the number of source bytes consumed. */ /* gzip file access functions */ /* This library supports reading and writing files in gzip (.gz) format with an interface similar to that of stdio, using the functions that start with "gz". The gzip format is different from the zlib format. gzip is a gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. */ typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ /* ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); Open the gzip (.gz) file at path for reading and decompressing, or compressing and writing. The mode parameter is as in fopen ("rb" or "wb") but can also include a compression level ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' for fixed code compression as in "wb9F". (See the description of deflateInit2 for more information about the strategy parameter.) 'T' will request transparent writing or appending with no compression and not using the gzip format. "a" can be used instead of "w" to request that the gzip stream that will be written be appended to the file. "+" will result in an error, since reading and writing to the same gzip file is not supported. The addition of "x" when writing will create the file exclusively, which fails if the file already exists. On systems that support it, the addition of "e" when reading or writing will set the flag to close the file on an execve() call. These functions, as well as gzip, will read and decode a sequence of gzip streams in a file. The append function of gzopen() can be used to create such a file. (Also see gzflush() for another way to do this.) When appending, gzopen does not test whether the file begins with a gzip stream, nor does it look for the end of the gzip streams to begin appending. gzopen will simply append a gzip stream to the existing file. gzopen can be used to read a file which is not in gzip format; in this case gzread will directly read from the file without decompression. When reading, this will be detected automatically by looking for the magic two- byte gzip header. gzopen returns NULL if the file could not be opened, if there was insufficient memory to allocate the gzFile state, or if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). errno can be checked to determine if the reason gzopen failed was that the file could not be opened. */ ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); /* Associate a gzFile with the file descriptor fd. File descriptors are obtained from calls like open, dup, creat, pipe or fileno (if the file has been previously opened with fopen). The mode parameter is as in gzopen. The next call of gzclose on the returned gzFile will also close the file descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, mode);. The duplicated descriptor should be saved to avoid a leak, since gzdopen does not close fd if it fails. If you are using fileno() to get the file descriptor from a FILE *, then you will have to use dup() to avoid double-close()ing the file descriptor. Both gzclose() and fclose() will close the associated file descriptor, so they need to have different file descriptors. gzdopen returns NULL if there was insufficient memory to allocate the gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not provided, or '+' was provided), or if fd is -1. The file descriptor is not used until the next gz* read, write, seek, or close operation, so gzdopen will not detect if fd is invalid (unless fd is -1). */ ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); /* Set the internal buffer size used by this library's functions for file to size. The default buffer size is 8192 bytes. This function must be called after gzopen() or gzdopen(), and before any other calls that read or write the file. The buffer memory allocation is always deferred to the first read or write. Three times that size in buffer space is allocated. A larger buffer size of, for example, 64K or 128K bytes will noticeably increase the speed of decompression (reading). The new buffer size also affects the maximum length for gzprintf(). gzbuffer() returns 0 on success, or -1 on failure, such as being called too late. */ ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); /* Dynamically update the compression level and strategy for file. See the description of deflateInit2 for the meaning of these parameters. Previously provided data is flushed before applying the parameter changes. gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not opened for writing, Z_ERRNO if there is an error writing the flushed data, or Z_MEM_ERROR if there is a memory allocation error. */ ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); /* Read and decompress up to len uncompressed bytes from file into buf. If the input file is not in gzip format, gzread copies the given number of bytes into the buffer directly from the file. After reaching the end of a gzip stream in the input, gzread will continue to read, looking for another gzip stream. Any number of gzip streams may be concatenated in the input file, and will all be decompressed by gzread(). If something other than a gzip stream is encountered after a gzip stream, that remaining trailing garbage is ignored (and no error is returned). gzread can be used to read a gzip file that is being concurrently written. Upon reaching the end of the input, gzread will return with the available data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then gzclearerr can be used to clear the end of file indicator in order to permit gzread to be tried again. Z_OK indicates that a gzip stream was completed on the last gzread. Z_BUF_ERROR indicates that the input file ended in the middle of a gzip stream. Note that gzread does not return -1 in the event of an incomplete gzip stream. This error is deferred until gzclose(), which will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip stream. Alternatively, gzerror can be used before gzclose to detect this case. gzread returns the number of uncompressed bytes actually read, less than len for end of file, or -1 for error. If len is too large to fit in an int, then nothing is read, -1 is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, gzFile file)); /* Read and decompress up to nitems items of size size from file into buf, otherwise operating as gzread() does. This duplicates the interface of stdio's fread(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfread() returns the number of full items read of size size, or zero if the end of the file was reached and a full item could not be read, or if there was an error. gzerror() must be consulted if zero is returned in order to determine if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is read, zero is returned, and the error state is set to Z_STREAM_ERROR. In the event that the end of file is reached and only a partial item is available at the end, i.e. the remaining uncompressed data length is not a multiple of size, then the final partial item is nevertheless read into buf and the end-of-file flag is set. The length of the partial item read is not provided, but could be inferred from the result of gztell(). This behavior is the same as the behavior of fread() implementations in common libraries, but it prevents the direct use of gzfread() to read a concurrently written file, resetting and retrying on end-of-file, when size is not 1. */ ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len)); /* Compress and write the len uncompressed bytes at buf to file. gzwrite returns the number of uncompressed bytes written or 0 in case of error. */ ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, z_size_t nitems, gzFile file)); /* Compress and write nitems items of size size from buf to file, duplicating the interface of stdio's fwrite(), with size_t request and return types. If the library defines size_t, then z_size_t is identical to size_t. If not, then z_size_t is an unsigned integer type that can contain a pointer. gzfwrite() returns the number of full items written of size size, or zero if there was an error. If the multiplication of size and nitems overflows, i.e. the product does not fit in a z_size_t, then nothing is written, zero is returned, and the error state is set to Z_STREAM_ERROR. */ ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); /* Convert, format, compress, and write the arguments (...) to file under control of the string format, as in fprintf. gzprintf returns the number of uncompressed bytes actually written, or a negative zlib error code in case of error. The number of uncompressed bytes written is limited to 8191, or one less than the buffer size given to gzbuffer(). The caller should assure that this limit is not exceeded. If it is exceeded, then gzprintf() will return an error (0) with nothing written. In this case, there may also be a buffer overflow with unpredictable consequences, which is possible only if zlib was compiled with the insecure functions sprintf() or vsprintf(), because the secure snprintf() or vsnprintf() functions were not available. This can be determined using zlibCompileFlags(). */ ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); /* Compress and write the given null-terminated string s to file, excluding the terminating null character. gzputs returns the number of characters written, or -1 in case of error. */ ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); /* Read and decompress bytes from file into buf, until len-1 characters are read, or until a newline character is read and transferred to buf, or an end-of-file condition is encountered. If any characters are read or if len is one, the string is terminated with a null character. If no characters are read due to an end-of-file or len is less than one, then the buffer is left untouched. gzgets returns buf which is a null-terminated string, or it returns NULL for end-of-file or in case of error. If there was an error, the contents at buf are indeterminate. */ ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); /* Compress and write c, converted to an unsigned char, into file. gzputc returns the value that was written, or -1 in case of error. */ ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); /* Read and decompress one byte from file. gzgetc returns this byte or -1 in case of end of file or error. This is implemented as a macro for speed. As such, it does not do all of the checking the other functions do. I.e. it does not check to see if file is NULL, nor whether the structure file points to has been clobbered or not. */ ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); /* Push c back onto the stream for file to be read as the first character on the next read. At least one character of push-back is always allowed. gzungetc() returns the character pushed, or -1 on failure. gzungetc() will fail if c is -1, and may fail if a character has been pushed but not read yet. If gzungetc is used immediately after gzopen or gzdopen, at least the output buffer size of pushed characters is allowed. (See gzbuffer above.) The pushed character will be discarded if the stream is repositioned with gzseek() or gzrewind(). */ ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); /* Flush all pending output to file. The parameter flush is as in the deflate() function. The return value is the zlib error number (see function gzerror below). gzflush is only permitted when writing. If the flush parameter is Z_FINISH, the remaining data is written and the gzip stream is completed in the output. If gzwrite() is called again, a new gzip stream will be started in the output. gzread() is able to read such concatenated gzip streams. gzflush should be called only when strictly necessary because it will degrade compression if called too often. */ /* ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence)); Set the starting position to offset relative to whence for the next gzread or gzwrite on file. The offset represents a number of bytes in the uncompressed data stream. The whence parameter is defined as in lseek(2); the value SEEK_END is not supported. If the file is opened for reading, this function is emulated but can be extremely slow. If the file is opened for writing, only forward seeks are supported; gzseek then compresses a sequence of zeroes up to the new starting position. gzseek returns the resulting offset location as measured in bytes from the beginning of the uncompressed stream, or -1 in case of error, in particular if the file is opened for writing and the new starting position would be before the current position. */ ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); /* Rewind file. This function is supported only for reading. gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET). */ /* ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); Return the starting position for the next gzread or gzwrite on file. This position represents a number of bytes in the uncompressed data stream, and is zero when starting, even if appending or reading a gzip stream from the middle of a file using gzdopen(). gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) */ /* ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); Return the current compressed (actual) read or write offset of file. This offset includes the count of bytes that precede the gzip stream, for example when appending or when using gzdopen() for reading. When reading, the offset does not include as yet unused buffered input. This information can be used for a progress indicator. On error, gzoffset() returns -1. */ ZEXTERN int ZEXPORT gzeof OF((gzFile file)); /* Return true (1) if the end-of-file indicator for file has been set while reading, false (0) otherwise. Note that the end-of-file indicator is set only if the read tried to go past the end of the input, but came up short. Therefore, just like feof(), gzeof() may return false even if there is no more data to read, in the event that the last read request was for the exact number of bytes remaining in the input file. This will happen if the input file size is an exact multiple of the buffer size. If gzeof() returns true, then the read functions will return no more data, unless the end-of-file indicator is reset by gzclearerr() and the input file has grown since the previous end of file was detected. */ ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); /* Return true (1) if file is being copied directly while reading, or false (0) if file is a gzip stream being decompressed. If the input file is empty, gzdirect() will return true, since the input does not contain a gzip stream. If gzdirect() is used immediately after gzopen() or gzdopen() it will cause buffers to be allocated to allow reading the file to determine if it is a gzip file. Therefore if gzbuffer() is used, it should be called before gzdirect(). When writing, gzdirect() returns true (1) if transparent writing was requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: gzdirect() is not needed when writing. Transparent writing must be explicitly requested, so the application already knows the answer. When linking statically, using gzdirect() will include all of the zlib code for gzip file reading and decompression, which may not be desired.) */ ZEXTERN int ZEXPORT gzclose OF((gzFile file)); /* Flush all pending output for file, if necessary, close file and deallocate the (de)compression state. Note that once file is closed, you cannot call gzerror with file, since its structures have been deallocated. gzclose must not be called more than once on the same file, just as free must not be called more than once on the same allocation. gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the last read ended in the middle of a gzip stream, or Z_OK on success. */ ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); /* Same as gzclose(), but gzclose_r() is only for use when reading, and gzclose_w() is only for use when writing or appending. The advantage to using these instead of gzclose() is that they avoid linking in zlib compression or decompression code that is not used when only reading or only writing respectively. If gzclose() is used, then both compression and decompression code will be included the application when linking to a static zlib library. */ ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); /* Return the error message for the last error which occurred on file. errnum is set to zlib error number. If an error occurred in the file system and not in the compression library, errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. The application must not modify the returned string. Future calls to this function may invalidate the previously returned string. If file is closed, then the string previously returned by gzerror will no longer be available. gzerror() should be used to distinguish errors from end-of-file for those functions above that do not distinguish those cases in their return values. */ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); /* Clear the error and end-of-file flags for file. This is analogous to the clearerr() function in stdio. This is useful for continuing to read a gzip file that is being written concurrently. */ #endif /* !Z_SOLO */ /* checksum functions */ /* These functions are not related to compression but are exported anyway because they might be useful in applications using the compression library. */ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); /* Update a running Adler-32 checksum with the bytes buf[0..len-1] and return the updated checksum. An Adler-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the checksum. An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed much faster. Usage example: uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error(); */ ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, z_size_t len)); /* Same as adler32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, z_off_t len2)); Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note that the z_off_t type (like off_t) is a signed integer. If len2 is negative, the result has no meaning or utility. */ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); /* Update a running CRC-32 with the bytes buf[0..len-1] and return the updated CRC-32. A CRC-32 value is in the range of a 32-bit unsigned integer. If buf is Z_NULL, this function returns the required initial value for the crc. Pre- and post-conditioning (one's complement) is performed within this function so it shouldn't be done by the application. Usage example: uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error(); */ ZEXTERN uLong ZEXPORT crc32_z OF((uLong crc, const Bytef *buf, z_size_t len)); /* Same as crc32(), but with a size_t length. */ /* ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); Combine two CRC-32 check values into one. For two sequences of bytes, seq1 and seq2 with lengths len1 and len2, CRC-32 check values were calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and len2. */ /* ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2)); Return the operator corresponding to length len2, to be used with crc32_combine_op(). */ ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op)); /* Give the same result as crc32_combine(), using op in place of len2. op is is generated from len2 by crc32_combine_gen(). This will be faster than crc32_combine() if the generated op is used more than once. */ /* various hacks, don't look :) */ /* deflateInit and inflateInit are macros to allow checking the zlib version * and the compiler's view of z_stream: */ ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, const char *version, int stream_size)); ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, const char *version, int stream_size)); ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)); #ifdef Z_PREFIX_SET # define z_deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define z_inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define z_inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #else # define deflateInit(strm, level) \ deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit(strm) \ inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) # define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) # define inflateInit2(strm, windowBits) \ inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ (int)sizeof(z_stream)) # define inflateBackInit(strm, windowBits, window) \ inflateBackInit_((strm), (windowBits), (window), \ ZLIB_VERSION, (int)sizeof(z_stream)) #endif #ifndef Z_SOLO /* gzgetc() macro and its supporting function and exposed data structure. Note * that the real internal state is much larger than the exposed structure. * This abbreviated structure exposes just enough for the gzgetc() macro. The * user should not mess with these exposed elements, since their names or * behavior could change in the future, perhaps even capriciously. They can * only be used by the gzgetc() macro. You have been warned. */ struct gzFile_s { unsigned have; unsigned char *next; z_off64_t pos; }; ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ #ifdef Z_PREFIX_SET # undef z_gzgetc # define z_gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #else # define gzgetc(g) \ ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) #endif /* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if * both are true, the application gets the *64 functions, and the regular * functions are changed to 64 bits) -- in case these are set on systems * without large file support, _LFS64_LARGEFILE must also be true */ #ifdef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t)); #endif #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) # ifdef Z_PREFIX_SET # define z_gzopen z_gzopen64 # define z_gzseek z_gzseek64 # define z_gztell z_gztell64 # define z_gzoffset z_gzoffset64 # define z_adler32_combine z_adler32_combine64 # define z_crc32_combine z_crc32_combine64 # define z_crc32_combine_gen z_crc32_combine_gen64 # else # define gzopen gzopen64 # define gzseek gzseek64 # define gztell gztell64 # define gzoffset gzoffset64 # define adler32_combine adler32_combine64 # define crc32_combine crc32_combine64 # define crc32_combine_gen crc32_combine_gen64 # endif # ifndef Z_LARGE64 ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t)); # endif #else ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); #endif #else /* Z_SOLO */ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t)); #endif /* !Z_SOLO */ /* undocumented functions */ ZEXTERN const char * ZEXPORT zError OF((int)); ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF((z_streamp)); ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); #if defined(_WIN32) && !defined(Z_SOLO) ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, const char *mode)); #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, const char *format, va_list va)); # endif #endif #ifdef __cplusplus } #endif #endif /* ZLIB_H */ PK!extlibs/__init__.pynu[PK! @@extlibs/zconf.hnu[/* zconf.h -- configuration of the zlib compression library * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ /* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H /* * If you *really* need a unique prefix for all types and library functions, * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * Even better than compiling with -DZ_PREFIX would be to use configure to set * this permanently in zconf.h using "./configure --zprefix". */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET /* all linked symbols and init macros */ # define _dist_code z__dist_code # define _length_code z__length_code # define _tr_align z__tr_align # define _tr_flush_bits z__tr_flush_bits # define _tr_flush_block z__tr_flush_block # define _tr_init z__tr_init # define _tr_stored_block z__tr_stored_block # define _tr_tally z__tr_tally # define adler32 z_adler32 # define adler32_combine z_adler32_combine # define adler32_combine64 z_adler32_combine64 # define adler32_z z_adler32_z # ifndef Z_SOLO # define compress z_compress # define compress2 z_compress2 # define compressBound z_compressBound # endif # define crc32 z_crc32 # define crc32_combine z_crc32_combine # define crc32_combine64 z_crc32_combine64 # define crc32_combine_gen z_crc32_combine_gen # define crc32_combine_gen64 z_crc32_combine_gen64 # define crc32_combine_op z_crc32_combine_op # define crc32_z z_crc32_z # define deflate z_deflate # define deflateBound z_deflateBound # define deflateCopy z_deflateCopy # define deflateEnd z_deflateEnd # define deflateGetDictionary z_deflateGetDictionary # define deflateInit z_deflateInit # define deflateInit2 z_deflateInit2 # define deflateInit2_ z_deflateInit2_ # define deflateInit_ z_deflateInit_ # define deflateParams z_deflateParams # define deflatePending z_deflatePending # define deflatePrime z_deflatePrime # define deflateReset z_deflateReset # define deflateResetKeep z_deflateResetKeep # define deflateSetDictionary z_deflateSetDictionary # define deflateSetHeader z_deflateSetHeader # define deflateTune z_deflateTune # define deflate_copyright z_deflate_copyright # define get_crc_table z_get_crc_table # ifndef Z_SOLO # define gz_error z_gz_error # define gz_intmax z_gz_intmax # define gz_strwinerror z_gz_strwinerror # define gzbuffer z_gzbuffer # define gzclearerr z_gzclearerr # define gzclose z_gzclose # define gzclose_r z_gzclose_r # define gzclose_w z_gzclose_w # define gzdirect z_gzdirect # define gzdopen z_gzdopen # define gzeof z_gzeof # define gzerror z_gzerror # define gzflush z_gzflush # define gzfread z_gzfread # define gzfwrite z_gzfwrite # define gzgetc z_gzgetc # define gzgetc_ z_gzgetc_ # define gzgets z_gzgets # define gzoffset z_gzoffset # define gzoffset64 z_gzoffset64 # define gzopen z_gzopen # define gzopen64 z_gzopen64 # ifdef _WIN32 # define gzopen_w z_gzopen_w # endif # define gzprintf z_gzprintf # define gzputc z_gzputc # define gzputs z_gzputs # define gzread z_gzread # define gzrewind z_gzrewind # define gzseek z_gzseek # define gzseek64 z_gzseek64 # define gzsetparams z_gzsetparams # define gztell z_gztell # define gztell64 z_gztell64 # define gzungetc z_gzungetc # define gzvprintf z_gzvprintf # define gzwrite z_gzwrite # endif # define inflate z_inflate # define inflateBack z_inflateBack # define inflateBackEnd z_inflateBackEnd # define inflateBackInit z_inflateBackInit # define inflateBackInit_ z_inflateBackInit_ # define inflateCodesUsed z_inflateCodesUsed # define inflateCopy z_inflateCopy # define inflateEnd z_inflateEnd # define inflateGetDictionary z_inflateGetDictionary # define inflateGetHeader z_inflateGetHeader # define inflateInit z_inflateInit # define inflateInit2 z_inflateInit2 # define inflateInit2_ z_inflateInit2_ # define inflateInit_ z_inflateInit_ # define inflateMark z_inflateMark # define inflatePrime z_inflatePrime # define inflateReset z_inflateReset # define inflateReset2 z_inflateReset2 # define inflateResetKeep z_inflateResetKeep # define inflateSetDictionary z_inflateSetDictionary # define inflateSync z_inflateSync # define inflateSyncPoint z_inflateSyncPoint # define inflateUndermine z_inflateUndermine # define inflateValidate z_inflateValidate # define inflate_copyright z_inflate_copyright # define inflate_fast z_inflate_fast # define inflate_table z_inflate_table # ifndef Z_SOLO # define uncompress z_uncompress # define uncompress2 z_uncompress2 # endif # define zError z_zError # ifndef Z_SOLO # define zcalloc z_zcalloc # define zcfree z_zcfree # endif # define zlibCompileFlags z_zlibCompileFlags # define zlibVersion z_zlibVersion /* all zlib typedefs in zlib.h and zconf.h */ # define Byte z_Byte # define Bytef z_Bytef # define alloc_func z_alloc_func # define charf z_charf # define free_func z_free_func # ifndef Z_SOLO # define gzFile z_gzFile # endif # define gz_header z_gz_header # define gz_headerp z_gz_headerp # define in_func z_in_func # define intf z_intf # define out_func z_out_func # define uInt z_uInt # define uIntf z_uIntf # define uLong z_uLong # define uLongf z_uLongf # define voidp z_voidp # define voidpc z_voidpc # define voidpf z_voidpf /* all zlib structs in zlib.h and zconf.h */ # define gz_header_s z_gz_header_s # define internal_state z_internal_state #endif #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS #endif #if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) # define OS2 #endif #if defined(_WINDOWS) && !defined(WINDOWS) # define WINDOWS #endif #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) # ifndef WIN32 # define WIN32 # endif #endif #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # ifndef SYS16BIT # define SYS16BIT # endif # endif #endif /* * Compile with -DMAXSEG_64K if the alloc function cannot allocate more * than 64k bytes at a time (needed on systems with 16-bit int). */ #ifdef SYS16BIT # define MAXSEG_64K #endif #ifdef MSDOS # define UNALIGNED_OK #endif #ifdef __STDC_VERSION__ # ifndef STDC # define STDC # endif # if __STDC_VERSION__ >= 199901L # ifndef STDC99 # define STDC99 # endif # endif #endif #if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) # define STDC #endif #if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) # define STDC #endif #if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) # define STDC #endif #if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) # define STDC #endif #if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ # define STDC #endif #ifndef STDC # ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ # define const /* note: need a more gentle solution here */ # endif #endif #if defined(ZLIB_CONST) && !defined(z_const) # define z_const const #else # define z_const #endif #ifdef Z_SOLO typedef unsigned long z_size_t; #else # define z_longlong long long # if defined(NO_SIZE_T) typedef unsigned NO_SIZE_T z_size_t; # elif defined(STDC) # include typedef size_t z_size_t; # else typedef unsigned long z_size_t; # endif # undef z_longlong #endif /* Maximum value for memLevel in deflateInit2 */ #ifndef MAX_MEM_LEVEL # ifdef MAXSEG_64K # define MAX_MEM_LEVEL 8 # else # define MAX_MEM_LEVEL 9 # endif #endif /* Maximum value for windowBits in deflateInit2 and inflateInit2. * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files * created by gzip. (Files created by minigzip can still be extracted by * gzip.) */ #ifndef MAX_WBITS # define MAX_WBITS 15 /* 32K LZ77 window */ #endif /* The memory requirements for deflate are (in bytes): (1 << (windowBits+2)) + (1 << (memLevel+9)) that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) plus a few kilobytes for small objects. For example, if you want to reduce the default memory requirements from 256K to 128K, compile with make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" Of course this will generally degrade compression (there's no free lunch). The memory requirements for inflate are (in bytes) 1 << windowBits that is, 32K for windowBits=15 (default value) plus about 7 kilobytes for small objects. */ /* Type declarations */ #ifndef OF /* function prototypes */ # ifdef STDC # define OF(args) args # else # define OF(args) () # endif #endif #ifndef Z_ARG /* function prototypes for stdarg */ # if defined(STDC) || defined(Z_HAVE_STDARG_H) # define Z_ARG(args) args # else # define Z_ARG(args) () # endif #endif /* The following definitions for FAR are needed only for MSDOS mixed * model programming (small or medium model with some far allocations). * This was tested only with MSC; for other MSDOS compilers you may have * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, * just define FAR to be empty. */ #ifdef SYS16BIT # if defined(M_I86SM) || defined(M_I86MM) /* MSC small or medium model */ # define SMALL_MEDIUM # ifdef _MSC_VER # define FAR _far # else # define FAR far # endif # endif # if (defined(__SMALL__) || defined(__MEDIUM__)) /* Turbo C small or medium model */ # define SMALL_MEDIUM # ifdef __BORLANDC__ # define FAR _far # else # define FAR far # endif # endif #endif #if defined(WINDOWS) || defined(WIN32) /* If building or using zlib as a DLL, define ZLIB_DLL. * This is not mandatory, but it offers a little performance increase. */ # ifdef ZLIB_DLL # if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) # ifdef ZLIB_INTERNAL # define ZEXTERN extern __declspec(dllexport) # else # define ZEXTERN extern __declspec(dllimport) # endif # endif # endif /* ZLIB_DLL */ /* If building or using zlib with the WINAPI/WINAPIV calling convention, * define ZLIB_WINAPI. * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. */ # ifdef ZLIB_WINAPI # ifdef FAR # undef FAR # endif # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # endif # include /* No need for _export, use ZLIB.DEF instead. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */ # define ZEXPORT WINAPI # ifdef WIN32 # define ZEXPORTVA WINAPIV # else # define ZEXPORTVA FAR CDECL # endif # endif #endif #if defined (__BEOS__) # ifdef ZLIB_DLL # ifdef ZLIB_INTERNAL # define ZEXPORT __declspec(dllexport) # define ZEXPORTVA __declspec(dllexport) # else # define ZEXPORT __declspec(dllimport) # define ZEXPORTVA __declspec(dllimport) # endif # endif #endif #ifndef ZEXTERN # define ZEXTERN extern #endif #ifndef ZEXPORT # define ZEXPORT #endif #ifndef ZEXPORTVA # define ZEXPORTVA #endif #ifndef FAR # define FAR #endif #if !defined(__MACTYPES__) typedef unsigned char Byte; /* 8 bits */ #endif typedef unsigned int uInt; /* 16 bits or more */ typedef unsigned long uLong; /* 32 bits or more */ #ifdef SMALL_MEDIUM /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ # define Bytef Byte FAR #else typedef Byte FAR Bytef; #endif typedef char FAR charf; typedef int FAR intf; typedef uInt FAR uIntf; typedef uLong FAR uLongf; #ifdef STDC typedef void const *voidpc; typedef void FAR *voidpf; typedef void *voidp; #else typedef Byte const *voidpc; typedef Byte FAR *voidpf; typedef Byte *voidp; #endif #if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) # include # if (UINT_MAX == 0xffffffffUL) # define Z_U4 unsigned # elif (ULONG_MAX == 0xffffffffUL) # define Z_U4 unsigned long # elif (USHRT_MAX == 0xffffffffUL) # define Z_U4 unsigned short # endif #endif #ifdef Z_U4 typedef Z_U4 z_crc_t; #else typedef unsigned long z_crc_t; #endif #if 1 /* was set to #if 1 by ./configure */ # define Z_HAVE_UNISTD_H #endif #if 1 /* was set to #if 1 by ./configure */ # define Z_HAVE_STDARG_H #endif #ifdef STDC # ifndef Z_SOLO # include /* for off_t */ # endif #endif #if defined(STDC) || defined(Z_HAVE_STDARG_H) # ifndef Z_SOLO # include /* for va_list */ # endif #endif #ifdef _WIN32 # ifndef Z_SOLO # include /* for wchar_t */ # endif #endif /* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even * though the former does not conform to the LFS document), but considering * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as * equivalently requesting no 64-bit operations */ #if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 # undef _LARGEFILE64_SOURCE #endif #ifndef Z_HAVE_UNISTD_H # ifdef __WATCOMC__ # define Z_HAVE_UNISTD_H # endif #endif #ifndef Z_HAVE_UNISTD_H # if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32) # define Z_HAVE_UNISTD_H # endif #endif #ifndef Z_SOLO # if defined(Z_HAVE_UNISTD_H) # include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # ifdef VMS # include /* for off_t */ # endif # ifndef z_off_t # define z_off_t off_t # endif # endif #endif #if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 # define Z_LFS64 #endif #if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) # define Z_LARGE64 #endif #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) # define Z_WANT64 #endif #if !defined(SEEK_SET) && !defined(Z_SOLO) # define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ #endif #ifndef z_off_t # define z_off_t long #endif #if !defined(_WIN32) && defined(Z_LARGE64) # define z_off64_t off64_t #else # if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) # define z_off64_t __int64 # else # define z_off64_t z_off_t # endif #endif /* MVS linker does not support external names larger than 8 bytes */ #if defined(__MVS__) #pragma map(deflateInit_,"DEIN") #pragma map(deflateInit2_,"DEIN2") #pragma map(deflateEnd,"DEEND") #pragma map(deflateBound,"DEBND") #pragma map(inflateInit_,"ININ") #pragma map(inflateInit2_,"ININ2") #pragma map(inflateEnd,"INEND") #pragma map(inflateSync,"INSY") #pragma map(inflateSetDictionary,"INSEDI") #pragma map(compressBound,"CMBND") #pragma map(inflate_table,"INTABL") #pragma map(inflate_fast,"INFA") #pragma map(inflate_copyright,"INCOPY") #endif #endif /* ZCONF_H */ PK!;textlibs/localcharset.hnu[/* Determine a canonical name for the current locale's character encoding. Copyright (C) 2000-2003, 2009-2019 Free Software Foundation, Inc. This file is part of the GNU CHARSET Library. This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, see . */ #ifndef _LOCALCHARSET_H #define _LOCALCHARSET_H #ifdef __cplusplus extern "C" { #endif /* Determine the current locale's character encoding, and canonicalize it into one of the canonical names listed below. The result must not be freed; it is statically allocated. The result becomes invalid when setlocale() is used to change the global locale, or when the value of one of the environment variables LC_ALL, LC_CTYPE, LANG is changed; threads in multithreaded programs should not do this. If the canonical name cannot be determined, the result is a non-canonical name. */ extern const char * locale_charset (void); /* About GNU canonical names for character encodings: Every canonical name must be supported by GNU libiconv. Support by GNU libc is also desirable. The name is case insensitive. Usually an upper case MIME charset name is preferred. The current list of these GNU canonical names is: name MIME? used by which systems (darwin = Mac OS X, windows = native Windows) ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin minix cygwin ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos ISO-8859-3 Y glibc solaris cygwin ISO-8859-4 Y hpux osf solaris freebsd netbsd openbsd darwin ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos ISO-8859-6 Y glibc aix hpux solaris cygwin ISO-8859-7 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin zos ISO-8859-8 Y glibc aix hpux osf solaris cygwin zos ISO-8859-9 Y glibc aix hpux irix osf solaris freebsd darwin cygwin zos ISO-8859-13 glibc hpux solaris freebsd netbsd openbsd darwin cygwin ISO-8859-14 glibc cygwin ISO-8859-15 glibc aix irix osf solaris freebsd netbsd openbsd darwin cygwin KOI8-R Y glibc hpux solaris freebsd netbsd openbsd darwin KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin KOI8-T glibc CP437 dos CP775 dos CP850 aix osf dos CP852 dos CP855 dos CP856 aix CP857 dos CP861 dos CP862 dos CP864 dos CP865 dos CP866 freebsd netbsd openbsd darwin dos CP869 dos CP874 windows dos CP922 aix CP932 aix cygwin windows dos CP943 aix zos CP949 osf darwin windows dos CP950 windows dos CP1046 aix CP1124 aix CP1125 dos CP1129 aix CP1131 freebsd darwin CP1250 windows CP1251 glibc hpux solaris freebsd netbsd openbsd darwin cygwin windows CP1252 aix windows CP1253 windows CP1254 windows CP1255 glibc windows CP1256 windows CP1257 windows GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin cygwin zos EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin zos EUC-TW glibc aix hpux irix osf solaris netbsd BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin zos BIG5-HKSCS glibc hpux solaris netbsd darwin GBK glibc aix osf solaris freebsd darwin cygwin windows dos GB18030 glibc hpux solaris freebsd netbsd darwin SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin JOHAB glibc solaris windows TIS-620 glibc aix hpux osf solaris cygwin zos VISCII Y glibc TCVN5712-1 glibc ARMSCII-8 glibc freebsd netbsd darwin GEORGIAN-PS glibc cygwin PT154 glibc netbsd cygwin HP-ROMAN8 hpux HP-ARABIC8 hpux HP-GREEK8 hpux HP-HEBREW8 hpux HP-TURKISH8 hpux HP-KANA8 hpux DEC-KANJI osf DEC-HANYU osf UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin zos Note: Names which are not marked as being a MIME name should not be used in Internet protocols for information interchange (mail, news, etc.). Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications must understand both names and treat them as equivalent. */ #ifdef __cplusplus } #endif #endif /* _LOCALCHARSET_H */ PK!% xmlschema.pxdnu[from lxml.includes.tree cimport xmlDoc from lxml.includes.xmlparser cimport xmlSAXHandler from lxml.includes.xmlerror cimport xmlStructuredErrorFunc cdef extern from "libxml/xmlschemas.h": ctypedef struct xmlSchema ctypedef struct xmlSchemaParserCtxt ctypedef struct xmlSchemaSAXPlugStruct ctypedef struct xmlSchemaValidCtxt ctypedef enum xmlSchemaValidOption: XML_SCHEMA_VAL_VC_I_CREATE = 1 cdef xmlSchemaValidCtxt* xmlSchemaNewValidCtxt(xmlSchema* schema) nogil cdef void xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxt* ctxt, xmlStructuredErrorFunc serror, void *ctx) cdef void xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxt* ctxt, xmlStructuredErrorFunc serror, void *ctx) cdef int xmlSchemaValidateDoc(xmlSchemaValidCtxt* ctxt, xmlDoc* doc) nogil cdef xmlSchema* xmlSchemaParse(xmlSchemaParserCtxt* ctxt) nogil cdef xmlSchemaParserCtxt* xmlSchemaNewParserCtxt(char* URL) nogil cdef xmlSchemaParserCtxt* xmlSchemaNewDocParserCtxt(xmlDoc* doc) nogil cdef void xmlSchemaFree(xmlSchema* schema) nogil cdef void xmlSchemaFreeParserCtxt(xmlSchemaParserCtxt* ctxt) nogil cdef void xmlSchemaFreeValidCtxt(xmlSchemaValidCtxt* ctxt) nogil cdef int xmlSchemaSetValidOptions(xmlSchemaValidCtxt* ctxt, int options) nogil cdef xmlSchemaSAXPlugStruct* xmlSchemaSAXPlug(xmlSchemaValidCtxt* ctxt, xmlSAXHandler** sax, void** data) nogil cdef int xmlSchemaSAXUnplug(xmlSchemaSAXPlugStruct* sax_plug) cdef int xmlSchemaIsValid(xmlSchemaValidCtxt* ctxt) PK!G{N{Ntree.pxdnu[from libc cimport stdio from libc.string cimport const_char, const_uchar cdef extern from "lxml-version.h": # deprecated declaration, use etreepublic.pxd instead cdef char* LXML_VERSION_STRING cdef extern from "libxml/xmlversion.h": cdef const_char* xmlParserVersion cdef int LIBXML_VERSION cdef extern from "libxml/xmlstring.h": ctypedef unsigned char xmlChar ctypedef const xmlChar const_xmlChar "const xmlChar" cdef int xmlStrlen(const_xmlChar* str) nogil cdef xmlChar* xmlStrdup(const_xmlChar* cur) nogil cdef int xmlStrncmp(const_xmlChar* str1, const_xmlChar* str2, int length) nogil cdef int xmlStrcmp(const_xmlChar* str1, const_xmlChar* str2) nogil cdef int xmlStrcasecmp(const xmlChar *str1, const xmlChar *str2) nogil cdef const_xmlChar* xmlStrstr(const_xmlChar* str1, const_xmlChar* str2) nogil cdef const_xmlChar* xmlStrchr(const_xmlChar* str1, xmlChar ch) nogil cdef const_xmlChar* _xcstr "(const xmlChar*)PyBytes_AS_STRING" (object s) cdef extern from "libxml/encoding.h": ctypedef enum xmlCharEncoding: XML_CHAR_ENCODING_ERROR = -1 # No char encoding detected XML_CHAR_ENCODING_NONE = 0 # No char encoding detected XML_CHAR_ENCODING_UTF8 = 1 # UTF-8 XML_CHAR_ENCODING_UTF16LE = 2 # UTF-16 little endian XML_CHAR_ENCODING_UTF16BE = 3 # UTF-16 big endian XML_CHAR_ENCODING_UCS4LE = 4 # UCS-4 little endian XML_CHAR_ENCODING_UCS4BE = 5 # UCS-4 big endian XML_CHAR_ENCODING_EBCDIC = 6 # EBCDIC uh! XML_CHAR_ENCODING_UCS4_2143 = 7 # UCS-4 unusual ordering XML_CHAR_ENCODING_UCS4_3412 = 8 # UCS-4 unusual ordering XML_CHAR_ENCODING_UCS2 = 9 # UCS-2 XML_CHAR_ENCODING_8859_1 = 10 # ISO-8859-1 ISO Latin 1 XML_CHAR_ENCODING_8859_2 = 11 # ISO-8859-2 ISO Latin 2 XML_CHAR_ENCODING_8859_3 = 12 # ISO-8859-3 XML_CHAR_ENCODING_8859_4 = 13 # ISO-8859-4 XML_CHAR_ENCODING_8859_5 = 14 # ISO-8859-5 XML_CHAR_ENCODING_8859_6 = 15 # ISO-8859-6 XML_CHAR_ENCODING_8859_7 = 16 # ISO-8859-7 XML_CHAR_ENCODING_8859_8 = 17 # ISO-8859-8 XML_CHAR_ENCODING_8859_9 = 18 # ISO-8859-9 XML_CHAR_ENCODING_2022_JP = 19 # ISO-2022-JP XML_CHAR_ENCODING_SHIFT_JIS = 20 # Shift_JIS XML_CHAR_ENCODING_EUC_JP = 21 # EUC-JP XML_CHAR_ENCODING_ASCII = 22 # pure ASCII ctypedef struct xmlCharEncodingHandler cdef xmlCharEncodingHandler* xmlFindCharEncodingHandler(char* name) nogil cdef xmlCharEncodingHandler* xmlGetCharEncodingHandler( xmlCharEncoding enc) nogil cdef int xmlCharEncCloseFunc(xmlCharEncodingHandler* handler) nogil cdef xmlCharEncoding xmlDetectCharEncoding(const_xmlChar* text, int len) nogil cdef const_char* xmlGetCharEncodingName(xmlCharEncoding enc) nogil cdef xmlCharEncoding xmlParseCharEncoding(char* name) nogil ctypedef int (*xmlCharEncodingOutputFunc)( unsigned char *out_buf, int *outlen, const_uchar *in_buf, int *inlen) cdef extern from "libxml/chvalid.h": cdef int xmlIsChar_ch(char c) nogil cdef int xmlIsCharQ(int ch) nogil cdef extern from "libxml/hash.h": ctypedef struct xmlHashTable ctypedef void (*xmlHashScanner)(void* payload, void* data, const_xmlChar* name) # may require GIL! void xmlHashScan(xmlHashTable* table, xmlHashScanner f, void* data) nogil void* xmlHashLookup(xmlHashTable* table, const_xmlChar* name) nogil ctypedef void (*xmlHashDeallocator)(void *payload, xmlChar *name) cdef xmlHashTable* xmlHashCreate(int size) cdef xmlHashTable* xmlHashCreateDict(int size, xmlDict *dict) cdef int xmlHashSize(xmlHashTable* table) cdef void xmlHashFree(xmlHashTable* table, xmlHashDeallocator f) cdef extern from *: # actually "libxml/dict.h" # libxml/dict.h appears to be broken to include in C ctypedef struct xmlDict cdef const_xmlChar* xmlDictLookup(xmlDict* dict, const_xmlChar* name, int len) nogil cdef const_xmlChar* xmlDictExists(xmlDict* dict, const_xmlChar* name, int len) nogil cdef int xmlDictOwns(xmlDict* dict, const_xmlChar* name) nogil cdef size_t xmlDictSize(xmlDict* dict) nogil cdef extern from "libxml/tree.h": ctypedef struct xmlDoc ctypedef struct xmlAttr ctypedef struct xmlNotationTable ctypedef enum xmlElementType: XML_ELEMENT_NODE= 1 XML_ATTRIBUTE_NODE= 2 XML_TEXT_NODE= 3 XML_CDATA_SECTION_NODE= 4 XML_ENTITY_REF_NODE= 5 XML_ENTITY_NODE= 6 XML_PI_NODE= 7 XML_COMMENT_NODE= 8 XML_DOCUMENT_NODE= 9 XML_DOCUMENT_TYPE_NODE= 10 XML_DOCUMENT_FRAG_NODE= 11 XML_NOTATION_NODE= 12 XML_HTML_DOCUMENT_NODE= 13 XML_DTD_NODE= 14 XML_ELEMENT_DECL= 15 XML_ATTRIBUTE_DECL= 16 XML_ENTITY_DECL= 17 XML_NAMESPACE_DECL= 18 XML_XINCLUDE_START= 19 XML_XINCLUDE_END= 20 ctypedef enum xmlElementTypeVal: XML_ELEMENT_TYPE_UNDEFINED= 0 XML_ELEMENT_TYPE_EMPTY= 1 XML_ELEMENT_TYPE_ANY= 2 XML_ELEMENT_TYPE_MIXED= 3 XML_ELEMENT_TYPE_ELEMENT= 4 ctypedef enum xmlElementContentType: XML_ELEMENT_CONTENT_PCDATA= 1 XML_ELEMENT_CONTENT_ELEMENT= 2 XML_ELEMENT_CONTENT_SEQ= 3 XML_ELEMENT_CONTENT_OR= 4 ctypedef enum xmlElementContentOccur: XML_ELEMENT_CONTENT_ONCE= 1 XML_ELEMENT_CONTENT_OPT= 2 XML_ELEMENT_CONTENT_MULT= 3 XML_ELEMENT_CONTENT_PLUS= 4 ctypedef enum xmlAttributeType: XML_ATTRIBUTE_CDATA = 1 XML_ATTRIBUTE_ID= 2 XML_ATTRIBUTE_IDREF= 3 XML_ATTRIBUTE_IDREFS= 4 XML_ATTRIBUTE_ENTITY= 5 XML_ATTRIBUTE_ENTITIES= 6 XML_ATTRIBUTE_NMTOKEN= 7 XML_ATTRIBUTE_NMTOKENS= 8 XML_ATTRIBUTE_ENUMERATION= 9 XML_ATTRIBUTE_NOTATION= 10 ctypedef enum xmlAttributeDefault: XML_ATTRIBUTE_NONE= 1 XML_ATTRIBUTE_REQUIRED= 2 XML_ATTRIBUTE_IMPLIED= 3 XML_ATTRIBUTE_FIXED= 4 ctypedef enum xmlEntityType: XML_INTERNAL_GENERAL_ENTITY= 1 XML_EXTERNAL_GENERAL_PARSED_ENTITY= 2 XML_EXTERNAL_GENERAL_UNPARSED_ENTITY= 3 XML_INTERNAL_PARAMETER_ENTITY= 4 XML_EXTERNAL_PARAMETER_ENTITY= 5 XML_INTERNAL_PREDEFINED_ENTITY= 6 ctypedef struct xmlNs: const_xmlChar* href const_xmlChar* prefix xmlNs* next ctypedef struct xmlNode: void* _private xmlElementType type const_xmlChar* name xmlNode* children xmlNode* last xmlNode* parent xmlNode* next xmlNode* prev xmlDoc* doc xmlChar* content xmlAttr* properties xmlNs* ns xmlNs* nsDef unsigned short line ctypedef struct xmlElementContent: xmlElementContentType type xmlElementContentOccur ocur const_xmlChar *name xmlElementContent *c1 xmlElementContent *c2 xmlElementContent *parent const_xmlChar *prefix ctypedef struct xmlEnumeration: xmlEnumeration *next const_xmlChar *name ctypedef struct xmlAttribute: void* _private xmlElementType type const_xmlChar* name xmlNode* children xmlNode* last xmlDtd* parent xmlNode* next xmlNode* prev xmlDoc* doc xmlAttribute* nexth xmlAttributeType atype xmlAttributeDefault def_ "def" const_xmlChar* defaultValue xmlEnumeration* tree const_xmlChar* prefix const_xmlChar* elem ctypedef struct xmlElement: void* _private xmlElementType type const_xmlChar* name xmlNode* children xmlNode* last xmlNode* parent xmlNode* next xmlNode* prev xmlDoc* doc xmlElementTypeVal etype xmlElementContent* content xmlAttribute* attributes const_xmlChar* prefix void *contModel ctypedef struct xmlEntity: void* _private xmlElementType type const_xmlChar* name xmlNode* children xmlNode* last xmlDtd* parent xmlNode* next xmlNode* prev xmlDoc* doc xmlChar* orig xmlChar* content int length xmlEntityType etype const_xmlChar* ExternalID const_xmlChar* SystemID xmlEntity* nexte const_xmlChar* URI int owner int checked ctypedef struct xmlDtd: const_xmlChar* name const_xmlChar* ExternalID const_xmlChar* SystemID void* notations void* entities void* pentities void* attributes void* elements xmlNode* children xmlNode* last xmlDoc* doc ctypedef struct xmlDoc: xmlElementType type char* name xmlNode* children xmlNode* last xmlNode* parent xmlNode* next xmlNode* prev xmlDoc* doc xmlDict* dict xmlHashTable* ids int standalone const_xmlChar* version const_xmlChar* encoding const_xmlChar* URL void* _private xmlDtd* intSubset xmlDtd* extSubset ctypedef struct xmlAttr: void* _private xmlElementType type const_xmlChar* name xmlNode* children xmlNode* last xmlNode* parent xmlAttr* next xmlAttr* prev xmlDoc* doc xmlNs* ns xmlAttributeType atype ctypedef struct xmlID: const_xmlChar* value const_xmlChar* name xmlAttr* attr xmlDoc* doc ctypedef struct xmlBuffer ctypedef struct xmlBuf # new in libxml2 2.9 ctypedef struct xmlOutputBuffer: xmlBuf* buffer xmlBuf* conv int error const_xmlChar* XML_XML_NAMESPACE cdef void xmlFreeDoc(xmlDoc* cur) nogil cdef void xmlFreeDtd(xmlDtd* cur) nogil cdef void xmlFreeNode(xmlNode* cur) nogil cdef void xmlFreeNsList(xmlNs* ns) nogil cdef void xmlFreeNs(xmlNs* ns) nogil cdef void xmlFree(void* buf) nogil cdef xmlNode* xmlNewNode(xmlNs* ns, const_xmlChar* name) nogil cdef xmlNode* xmlNewDocText(xmlDoc* doc, const_xmlChar* content) nogil cdef xmlNode* xmlNewDocComment(xmlDoc* doc, const_xmlChar* content) nogil cdef xmlNode* xmlNewDocPI(xmlDoc* doc, const_xmlChar* name, const_xmlChar* content) nogil cdef xmlNode* xmlNewReference(xmlDoc* doc, const_xmlChar* name) nogil cdef xmlNode* xmlNewCDataBlock(xmlDoc* doc, const_xmlChar* text, int len) nogil cdef xmlNs* xmlNewNs(xmlNode* node, const_xmlChar* href, const_xmlChar* prefix) nogil cdef xmlNode* xmlAddChild(xmlNode* parent, xmlNode* cur) nogil cdef xmlNode* xmlReplaceNode(xmlNode* old, xmlNode* cur) nogil cdef xmlNode* xmlAddPrevSibling(xmlNode* cur, xmlNode* elem) nogil cdef xmlNode* xmlAddNextSibling(xmlNode* cur, xmlNode* elem) nogil cdef xmlNode* xmlNewDocNode(xmlDoc* doc, xmlNs* ns, const_xmlChar* name, const_xmlChar* content) nogil cdef xmlDoc* xmlNewDoc(const_xmlChar* version) nogil cdef xmlAttr* xmlNewProp(xmlNode* node, const_xmlChar* name, const_xmlChar* value) nogil cdef xmlAttr* xmlNewNsProp(xmlNode* node, xmlNs* ns, const_xmlChar* name, const_xmlChar* value) nogil cdef xmlChar* xmlGetNoNsProp(xmlNode* node, const_xmlChar* name) nogil cdef xmlChar* xmlGetNsProp(xmlNode* node, const_xmlChar* name, const_xmlChar* nameSpace) nogil cdef void xmlSetNs(xmlNode* node, xmlNs* ns) nogil cdef xmlAttr* xmlSetProp(xmlNode* node, const_xmlChar* name, const_xmlChar* value) nogil cdef xmlAttr* xmlSetNsProp(xmlNode* node, xmlNs* ns, const_xmlChar* name, const_xmlChar* value) nogil cdef int xmlRemoveID(xmlDoc* doc, xmlAttr* cur) nogil cdef int xmlRemoveProp(xmlAttr* cur) nogil cdef void xmlFreePropList(xmlAttr* cur) nogil cdef xmlChar* xmlGetNodePath(xmlNode* node) nogil cdef void xmlDocDumpMemory(xmlDoc* cur, char** mem, int* size) nogil cdef void xmlDocDumpMemoryEnc(xmlDoc* cur, char** mem, int* size, char* encoding) nogil cdef int xmlSaveFileTo(xmlOutputBuffer* out, xmlDoc* cur, char* encoding) nogil cdef void xmlUnlinkNode(xmlNode* cur) nogil cdef xmlNode* xmlDocSetRootElement(xmlDoc* doc, xmlNode* root) nogil cdef xmlNode* xmlDocGetRootElement(xmlDoc* doc) nogil cdef void xmlSetTreeDoc(xmlNode* tree, xmlDoc* doc) nogil cdef xmlAttr* xmlHasProp(xmlNode* node, const_xmlChar* name) nogil cdef xmlAttr* xmlHasNsProp(xmlNode* node, const_xmlChar* name, const_xmlChar* nameSpace) nogil cdef xmlChar* xmlNodeGetContent(xmlNode* cur) nogil cdef int xmlNodeBufGetContent(xmlBuffer* buffer, xmlNode* cur) nogil cdef xmlNs* xmlSearchNs(xmlDoc* doc, xmlNode* node, const_xmlChar* prefix) nogil cdef xmlNs* xmlSearchNsByHref(xmlDoc* doc, xmlNode* node, const_xmlChar* href) nogil cdef int xmlIsBlankNode(xmlNode* node) nogil cdef long xmlGetLineNo(xmlNode* node) nogil cdef void xmlElemDump(stdio.FILE* f, xmlDoc* doc, xmlNode* cur) nogil cdef void xmlNodeDumpOutput(xmlOutputBuffer* buf, xmlDoc* doc, xmlNode* cur, int level, int format, const_char* encoding) nogil cdef void xmlBufAttrSerializeTxtContent(xmlOutputBuffer *buf, xmlDoc *doc, xmlAttr *attr, const_xmlChar *string) nogil cdef void xmlNodeSetName(xmlNode* cur, const_xmlChar* name) nogil cdef void xmlNodeSetContent(xmlNode* cur, const_xmlChar* content) nogil cdef xmlDtd* xmlCopyDtd(xmlDtd* dtd) nogil cdef xmlDoc* xmlCopyDoc(xmlDoc* doc, int recursive) nogil cdef xmlNode* xmlCopyNode(xmlNode* node, int extended) nogil cdef xmlNode* xmlDocCopyNode(xmlNode* node, xmlDoc* doc, int extended) nogil cdef int xmlReconciliateNs(xmlDoc* doc, xmlNode* tree) nogil cdef xmlNs* xmlNewReconciliedNs(xmlDoc* doc, xmlNode* tree, xmlNs* ns) nogil cdef xmlBuffer* xmlBufferCreate() nogil cdef void xmlBufferWriteChar(xmlBuffer* buf, char* string) nogil cdef void xmlBufferFree(xmlBuffer* buf) nogil cdef const_xmlChar* xmlBufferContent(xmlBuffer* buf) nogil cdef int xmlBufferLength(xmlBuffer* buf) nogil cdef const_xmlChar* xmlBufContent(xmlBuf* buf) nogil # new in libxml2 2.9 cdef size_t xmlBufUse(xmlBuf* buf) nogil # new in libxml2 2.9 cdef int xmlKeepBlanksDefault(int val) nogil cdef xmlChar* xmlNodeGetBase(xmlDoc* doc, xmlNode* node) nogil cdef xmlDtd* xmlCreateIntSubset(xmlDoc* doc, const_xmlChar* name, const_xmlChar* ExternalID, const_xmlChar* SystemID) nogil cdef void xmlNodeSetBase(xmlNode* node, const_xmlChar* uri) nogil cdef int xmlValidateNCName(const_xmlChar* value, int space) nogil cdef extern from "libxml/uri.h": cdef const_xmlChar* xmlBuildURI(const_xmlChar* href, const_xmlChar* base) nogil cdef extern from "libxml/HTMLtree.h": cdef void htmlNodeDumpFormatOutput(xmlOutputBuffer* buf, xmlDoc* doc, xmlNode* cur, char* encoding, int format) nogil cdef xmlDoc* htmlNewDoc(const_xmlChar* uri, const_xmlChar* externalID) nogil cdef extern from "libxml/valid.h": cdef xmlAttr* xmlGetID(xmlDoc* doc, const_xmlChar* ID) nogil cdef void xmlDumpNotationTable(xmlBuffer* buffer, xmlNotationTable* table) nogil cdef int xmlValidateNameValue(const_xmlChar* value) nogil cdef extern from "libxml/xmlIO.h": cdef int xmlOutputBufferWrite(xmlOutputBuffer* out, int len, const_char* str) nogil cdef int xmlOutputBufferWriteString(xmlOutputBuffer* out, const_char* str) nogil cdef int xmlOutputBufferWriteEscape(xmlOutputBuffer* out, const_xmlChar* str, xmlCharEncodingOutputFunc escapefunc) nogil cdef int xmlOutputBufferFlush(xmlOutputBuffer* out) nogil cdef int xmlOutputBufferClose(xmlOutputBuffer* out) nogil ctypedef int (*xmlInputReadCallback)(void* context, char* buffer, int len) ctypedef int (*xmlInputCloseCallback)(void* context) ctypedef int (*xmlOutputWriteCallback)(void* context, char* buffer, int len) ctypedef int (*xmlOutputCloseCallback)(void* context) cdef xmlOutputBuffer* xmlAllocOutputBuffer( xmlCharEncodingHandler* encoder) nogil cdef xmlOutputBuffer* xmlOutputBufferCreateIO( xmlOutputWriteCallback iowrite, xmlOutputCloseCallback ioclose, void * ioctx, xmlCharEncodingHandler* encoder) nogil cdef xmlOutputBuffer* xmlOutputBufferCreateFile( stdio.FILE* file, xmlCharEncodingHandler* encoder) nogil cdef xmlOutputBuffer* xmlOutputBufferCreateFilename( char* URI, xmlCharEncodingHandler* encoder, int compression) nogil cdef extern from "libxml/xmlsave.h": ctypedef struct xmlSaveCtxt ctypedef enum xmlSaveOption: XML_SAVE_FORMAT = 1 # format save output (2.6.17) XML_SAVE_NO_DECL = 2 # drop the xml declaration (2.6.21) XML_SAVE_NO_EMPTY = 4 # no empty tags (2.6.22) XML_SAVE_NO_XHTML = 8 # disable XHTML1 specific rules (2.6.22) XML_SAVE_XHTML = 16 # force XHTML1 specific rules (2.7.2) XML_SAVE_AS_XML = 32 # force XML serialization on HTML doc (2.7.2) XML_SAVE_AS_HTML = 64 # force HTML serialization on XML doc (2.7.2) cdef xmlSaveCtxt* xmlSaveToFilename(char* filename, char* encoding, int options) nogil cdef xmlSaveCtxt* xmlSaveToBuffer(xmlBuffer* buffer, char* encoding, int options) nogil # libxml2 2.6.23 cdef long xmlSaveDoc(xmlSaveCtxt* ctxt, xmlDoc* doc) nogil cdef long xmlSaveTree(xmlSaveCtxt* ctxt, xmlNode* node) nogil cdef int xmlSaveClose(xmlSaveCtxt* ctxt) nogil cdef int xmlSaveFlush(xmlSaveCtxt* ctxt) nogil cdef int xmlSaveSetAttrEscape(xmlSaveCtxt* ctxt, void* escape_func) nogil cdef int xmlSaveSetEscape(xmlSaveCtxt* ctxt, void* escape_func) nogil cdef extern from "libxml/globals.h": cdef int xmlThrDefKeepBlanksDefaultValue(int onoff) nogil cdef int xmlThrDefLineNumbersDefaultValue(int onoff) nogil cdef int xmlThrDefIndentTreeOutput(int onoff) nogil cdef extern from "libxml/xmlmemory.h" nogil: cdef void* xmlMalloc(size_t size) cdef int xmlMemBlocks() cdef int xmlMemUsed() cdef void xmlMemDisplay(stdio.FILE* file) cdef void xmlMemDisplayLast(stdio.FILE* file, long num_bytes) cdef void xmlMemShow(stdio.FILE* file, int count) cdef extern from "etree_defs.h": cdef bint _isElement(xmlNode* node) nogil cdef bint _isElementOrXInclude(xmlNode* node) nogil cdef const_xmlChar* _getNs(xmlNode* node) nogil cdef void BEGIN_FOR_EACH_ELEMENT_FROM(xmlNode* tree_top, xmlNode* start_node, bint inclusive) nogil cdef void END_FOR_EACH_ELEMENT_FROM(xmlNode* start_node) nogil cdef void BEGIN_FOR_EACH_FROM(xmlNode* tree_top, xmlNode* start_node, bint inclusive) nogil cdef void END_FOR_EACH_FROM(xmlNode* start_node) nogil PK!u*u* xmlparser.pxdnu[from libc.string cimport const_char from lxml.includes.tree cimport ( xmlDoc, xmlNode, xmlDict, xmlDtd, xmlChar, const_xmlChar) from lxml.includes.tree cimport xmlInputReadCallback, xmlInputCloseCallback from lxml.includes.xmlerror cimport xmlError, xmlStructuredErrorFunc cdef extern from "libxml/parser.h": ctypedef void (*startElementNsSAX2Func)(void* ctx, const_xmlChar* localname, const_xmlChar* prefix, const_xmlChar* URI, int nb_namespaces, const_xmlChar** namespaces, int nb_attributes, int nb_defaulted, const_xmlChar** attributes) ctypedef void (*endElementNsSAX2Func)(void* ctx, const_xmlChar* localname, const_xmlChar* prefix, const_xmlChar* URI) ctypedef void (*startElementSAXFunc)(void* ctx, const_xmlChar* name, const_xmlChar** atts) ctypedef void (*endElementSAXFunc)(void* ctx, const_xmlChar* name) ctypedef void (*charactersSAXFunc)(void* ctx, const_xmlChar* ch, int len) ctypedef void (*cdataBlockSAXFunc)(void* ctx, const_xmlChar* value, int len) ctypedef void (*commentSAXFunc)(void* ctx, const_xmlChar* value) ctypedef void (*processingInstructionSAXFunc)(void* ctx, const_xmlChar* target, const_xmlChar* data) ctypedef void (*internalSubsetSAXFunc)(void* ctx, const_xmlChar* name, const_xmlChar* externalID, const_xmlChar* systemID) ctypedef void (*endDocumentSAXFunc)(void* ctx) ctypedef void (*startDocumentSAXFunc)(void* ctx) ctypedef void (*referenceSAXFunc)(void * ctx, const_xmlChar* name) cdef int XML_SAX2_MAGIC cdef extern from "libxml/tree.h": ctypedef struct xmlParserInput: int line int length const_xmlChar* base const_xmlChar* cur const_xmlChar* end const_char *filename ctypedef struct xmlParserInputBuffer: void* context xmlInputReadCallback readcallback xmlInputCloseCallback closecallback ctypedef struct xmlSAXHandlerV1: # same as xmlSAXHandler, but without namespaces pass ctypedef struct xmlSAXHandler: internalSubsetSAXFunc internalSubset startElementNsSAX2Func startElementNs endElementNsSAX2Func endElementNs startElementSAXFunc startElement endElementSAXFunc endElement charactersSAXFunc characters cdataBlockSAXFunc cdataBlock referenceSAXFunc reference commentSAXFunc comment processingInstructionSAXFunc processingInstruction startDocumentSAXFunc startDocument endDocumentSAXFunc endDocument int initialized xmlStructuredErrorFunc serror void* _private cdef extern from "libxml/SAX2.h" nogil: cdef void xmlSAX2StartDocument(void* ctxt) cdef extern from "libxml/xmlIO.h" nogil: cdef xmlParserInputBuffer* xmlAllocParserInputBuffer(int enc) cdef extern from "libxml/parser.h": cdef xmlDict* xmlDictCreate() nogil cdef xmlDict* xmlDictCreateSub(xmlDict* subdict) nogil cdef void xmlDictFree(xmlDict* sub) nogil cdef int xmlDictReference(xmlDict* dict) nogil cdef int XML_COMPLETE_ATTRS # SAX option for adding DTD default attributes cdef int XML_SKIP_IDS # SAX option for not building an XML ID dict ctypedef enum xmlParserInputState: XML_PARSER_EOF = -1 # nothing is to be parsed XML_PARSER_START = 0 # nothing has been parsed XML_PARSER_MISC = 1 # Misc* before int subset XML_PARSER_PI = 2 # Within a processing instruction XML_PARSER_DTD = 3 # within some DTD content XML_PARSER_PROLOG = 4 # Misc* after internal subset XML_PARSER_COMMENT = 5 # within a comment XML_PARSER_START_TAG = 6 # within a start tag XML_PARSER_CONTENT = 7 # within the content XML_PARSER_CDATA_SECTION = 8 # within a CDATA section XML_PARSER_END_TAG = 9 # within a closing tag XML_PARSER_ENTITY_DECL = 10 # within an entity declaration XML_PARSER_ENTITY_VALUE = 11 # within an entity value in a decl XML_PARSER_ATTRIBUTE_VALUE = 12 # within an attribute value XML_PARSER_SYSTEM_LITERAL = 13 # within a SYSTEM value XML_PARSER_EPILOG = 14 # the Misc* after the last end tag XML_PARSER_IGNORE = 15 # within an IGNORED section XML_PARSER_PUBLIC_LITERAL = 16 # within a PUBLIC value ctypedef struct xmlParserCtxt: xmlDoc* myDoc xmlDict* dict int dictNames void* _private bint wellFormed bint recovery int options bint disableSAX int errNo xmlParserInputState instate bint replaceEntities int loadsubset # != 0 if enabled, int value == why bint validate xmlError lastError xmlNode* node xmlSAXHandler* sax void* userData int* spaceTab int spaceMax int nsNr bint html bint progressive int inSubset int charset xmlParserInput* input ctypedef enum xmlParserOption: XML_PARSE_RECOVER = 1 # recover on errors XML_PARSE_NOENT = 2 # substitute entities XML_PARSE_DTDLOAD = 4 # load the external subset XML_PARSE_DTDATTR = 8 # default DTD attributes XML_PARSE_DTDVALID = 16 # validate with the DTD XML_PARSE_NOERROR = 32 # suppress error reports XML_PARSE_NOWARNING = 64 # suppress warning reports XML_PARSE_PEDANTIC = 128 # pedantic error reporting XML_PARSE_NOBLANKS = 256 # remove blank nodes XML_PARSE_SAX1 = 512 # use the SAX1 interface internally XML_PARSE_XINCLUDE = 1024 # Implement XInclude substitution XML_PARSE_NONET = 2048 # Forbid network access XML_PARSE_NODICT = 4096 # Do not reuse the context dictionary XML_PARSE_NSCLEAN = 8192 # remove redundant namespaces declarations XML_PARSE_NOCDATA = 16384 # merge CDATA as text nodes XML_PARSE_NOXINCNODE = 32768 # do not generate XINCLUDE START/END nodes # libxml2 2.6.21+ only: XML_PARSE_COMPACT = 65536 # compact small text nodes # libxml2 2.7.0+ only: XML_PARSE_OLD10 = 131072 # parse using XML-1.0 before update 5 XML_PARSE_NOBASEFIX = 262144 # do not fixup XINCLUDE xml:base uris XML_PARSE_HUGE = 524288 # relax any hardcoded limit from the parser # libxml2 2.7.3+ only: XML_PARSE_OLDSAX = 1048576 # parse using SAX2 interface before 2.7.0 # libxml2 2.8.0+ only: XML_PARSE_IGNORE_ENC = 2097152 # ignore internal document encoding hint # libxml2 2.9.0+ only: XML_PARSE_BIG_LINES = 4194304 # Store big lines numbers in text PSVI field cdef void xmlInitParser() nogil cdef void xmlCleanupParser() nogil cdef int xmlLineNumbersDefault(int onoff) nogil cdef xmlParserCtxt* xmlNewParserCtxt() nogil cdef xmlParserInput* xmlNewIOInputStream(xmlParserCtxt* ctxt, xmlParserInputBuffer* input, int enc) nogil cdef int xmlCtxtUseOptions(xmlParserCtxt* ctxt, int options) nogil cdef void xmlFreeParserCtxt(xmlParserCtxt* ctxt) nogil cdef void xmlCtxtReset(xmlParserCtxt* ctxt) nogil cdef void xmlClearParserCtxt(xmlParserCtxt* ctxt) nogil cdef int xmlParseChunk(xmlParserCtxt* ctxt, char* chunk, int size, int terminate) nogil cdef xmlDoc* xmlCtxtReadDoc(xmlParserCtxt* ctxt, char* cur, char* URL, char* encoding, int options) nogil cdef xmlDoc* xmlCtxtReadFile(xmlParserCtxt* ctxt, char* filename, char* encoding, int options) nogil cdef xmlDoc* xmlCtxtReadIO(xmlParserCtxt* ctxt, xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void* ioctx, char* URL, char* encoding, int options) nogil cdef xmlDoc* xmlCtxtReadMemory(xmlParserCtxt* ctxt, char* buffer, int size, char* filename, const_char* encoding, int options) nogil # iterparse: cdef xmlParserCtxt* xmlCreatePushParserCtxt(xmlSAXHandler* sax, void* user_data, char* chunk, int size, char* filename) nogil cdef int xmlCtxtResetPush(xmlParserCtxt* ctxt, char* chunk, int size, char* filename, char* encoding) nogil # entity loaders: ctypedef xmlParserInput* (*xmlExternalEntityLoader)( const_char * URL, const_char * ID, xmlParserCtxt* context) nogil cdef xmlExternalEntityLoader xmlGetExternalEntityLoader() nogil cdef void xmlSetExternalEntityLoader(xmlExternalEntityLoader f) nogil # DTDs: cdef xmlDtd* xmlParseDTD(const_xmlChar* ExternalID, const_xmlChar* SystemID) nogil cdef xmlDtd* xmlIOParseDTD(xmlSAXHandler* sax, xmlParserInputBuffer* input, int enc) nogil cdef extern from "libxml/parserInternals.h": cdef xmlParserInput* xmlNewInputStream(xmlParserCtxt* ctxt) cdef xmlParserInput* xmlNewStringInputStream(xmlParserCtxt* ctxt, char* buffer) nogil cdef xmlParserInput* xmlNewInputFromFile(xmlParserCtxt* ctxt, char* filename) nogil cdef void xmlFreeInputStream(xmlParserInput* input) nogil cdef int xmlSwitchEncoding(xmlParserCtxt* ctxt, int enc) nogil PK!g@ xpath.pxdnu[from lxml.includes cimport tree from lxml.includes cimport xmlerror from libc.string cimport const_char from lxml.includes.tree cimport xmlChar, const_xmlChar cdef extern from "libxml/xpath.h": ctypedef enum xmlXPathObjectType: XPATH_UNDEFINED = 0 XPATH_NODESET = 1 XPATH_BOOLEAN = 2 XPATH_NUMBER = 3 XPATH_STRING = 4 XPATH_POINT = 5 XPATH_RANGE = 6 XPATH_LOCATIONSET = 7 XPATH_USERS = 8 XPATH_XSLT_TREE = 9 ctypedef enum xmlXPathError: XPATH_EXPRESSION_OK = 0 XPATH_NUMBER_ERROR = 1 XPATH_UNFINISHED_LITERAL_ERROR = 2 XPATH_START_LITERAL_ERROR = 3 XPATH_VARIABLE_REF_ERROR = 4 XPATH_UNDEF_VARIABLE_ERROR = 5 XPATH_INVALID_PREDICATE_ERROR = 6 XPATH_EXPR_ERROR = 7 XPATH_UNCLOSED_ERROR = 8 XPATH_UNKNOWN_FUNC_ERROR = 9 XPATH_INVALID_OPERAND = 10 XPATH_INVALID_TYPE = 11 XPATH_INVALID_ARITY = 12 XPATH_INVALID_CTXT_SIZE = 13 XPATH_INVALID_CTXT_POSITION = 14 XPATH_MEMORY_ERROR = 15 XPTR_SYNTAX_ERROR = 16 XPTR_RESOURCE_ERROR = 17 XPTR_SUB_RESOURCE_ERROR = 18 XPATH_UNDEF_PREFIX_ERROR = 19 XPATH_ENCODING_ERROR = 20 XPATH_INVALID_CHAR_ERROR = 21 XPATH_INVALID_CTXT = 22 ctypedef struct xmlNodeSet: int nodeNr int nodeMax tree.xmlNode** nodeTab ctypedef struct xmlXPathObject: xmlXPathObjectType type xmlNodeSet* nodesetval bint boolval double floatval xmlChar* stringval ctypedef struct xmlXPathContext: tree.xmlDoc* doc tree.xmlNode* node tree.xmlDict* dict tree.xmlHashTable* nsHash const_xmlChar* function const_xmlChar* functionURI xmlerror.xmlStructuredErrorFunc error xmlerror.xmlError lastError void* userData ctypedef struct xmlXPathParserContext: xmlXPathContext* context xmlXPathObject* value tree.xmlNode* ancestor int error ctypedef struct xmlXPathCompExpr ctypedef void (*xmlXPathFunction)(xmlXPathParserContext* ctxt, int nargs) nogil ctypedef xmlXPathFunction (*xmlXPathFuncLookupFunc)(void* ctxt, const_xmlChar* name, const_xmlChar* ns_uri) nogil cdef xmlXPathContext* xmlXPathNewContext(tree.xmlDoc* doc) nogil cdef xmlXPathObject* xmlXPathEvalExpression(const_xmlChar* str, xmlXPathContext* ctxt) nogil cdef xmlXPathObject* xmlXPathCompiledEval(xmlXPathCompExpr* comp, xmlXPathContext* ctxt) nogil cdef xmlXPathCompExpr* xmlXPathCompile(const_xmlChar* str) nogil cdef xmlXPathCompExpr* xmlXPathCtxtCompile(xmlXPathContext* ctxt, const_xmlChar* str) nogil cdef void xmlXPathFreeContext(xmlXPathContext* ctxt) nogil cdef void xmlXPathFreeCompExpr(xmlXPathCompExpr* comp) nogil cdef void xmlXPathFreeObject(xmlXPathObject* obj) nogil cdef int xmlXPathRegisterNs(xmlXPathContext* ctxt, const_xmlChar* prefix, const_xmlChar* ns_uri) nogil cdef xmlNodeSet* xmlXPathNodeSetCreate(tree.xmlNode* val) nogil cdef void xmlXPathFreeNodeSet(xmlNodeSet* val) nogil cdef extern from "libxml/xpathInternals.h": cdef int xmlXPathRegisterFunc(xmlXPathContext* ctxt, const_xmlChar* name, xmlXPathFunction f) nogil cdef int xmlXPathRegisterFuncNS(xmlXPathContext* ctxt, const_xmlChar* name, const_xmlChar* ns_uri, xmlXPathFunction f) nogil cdef void xmlXPathRegisterFuncLookup(xmlXPathContext *ctxt, xmlXPathFuncLookupFunc f, void *funcCtxt) nogil cdef int xmlXPathRegisterVariable(xmlXPathContext *ctxt, const_xmlChar* name, xmlXPathObject* value) nogil cdef int xmlXPathRegisterVariableNS(xmlXPathContext *ctxt, const_xmlChar* name, const_xmlChar* ns_uri, xmlXPathObject* value) nogil cdef void xmlXPathRegisteredVariablesCleanup(xmlXPathContext *ctxt) nogil cdef void xmlXPathRegisteredNsCleanup(xmlXPathContext *ctxt) nogil cdef xmlXPathObject* valuePop (xmlXPathParserContext *ctxt) nogil cdef int valuePush(xmlXPathParserContext* ctxt, xmlXPathObject *value) nogil cdef xmlXPathObject* xmlXPathNewCString(const_char *val) nogil cdef xmlXPathObject* xmlXPathWrapCString(const_char * val) nogil cdef xmlXPathObject* xmlXPathNewString(const_xmlChar *val) nogil cdef xmlXPathObject* xmlXPathWrapString(const_xmlChar * val) nogil cdef xmlXPathObject* xmlXPathNewFloat(double val) nogil cdef xmlXPathObject* xmlXPathNewBoolean(int val) nogil cdef xmlXPathObject* xmlXPathNewNodeSet(tree.xmlNode* val) nogil cdef xmlXPathObject* xmlXPathNewValueTree(tree.xmlNode* val) nogil cdef void xmlXPathNodeSetAdd(xmlNodeSet* cur, tree.xmlNode* val) nogil cdef void xmlXPathNodeSetAddUnique(xmlNodeSet* cur, tree.xmlNode* val) nogil cdef xmlXPathObject* xmlXPathWrapNodeSet(xmlNodeSet* val) nogil cdef void xmlXPathErr(xmlXPathParserContext* ctxt, int error) nogil PK!Yٔٔ libxml/tree.hnu[/* * Summary: interfaces for tree manipulation * Description: this module describes the structures found in an tree resulting * from an XML or HTML parsing, as well as the API provided for * various processing on that tree * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_TREE_H__ #define __XML_TREE_H__ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Some of the basic types pointer to structures: */ /* xmlIO.h */ typedef struct _xmlParserInputBuffer xmlParserInputBuffer; typedef xmlParserInputBuffer *xmlParserInputBufferPtr; typedef struct _xmlOutputBuffer xmlOutputBuffer; typedef xmlOutputBuffer *xmlOutputBufferPtr; /* parser.h */ typedef struct _xmlParserInput xmlParserInput; typedef xmlParserInput *xmlParserInputPtr; typedef struct _xmlParserCtxt xmlParserCtxt; typedef xmlParserCtxt *xmlParserCtxtPtr; typedef struct _xmlSAXLocator xmlSAXLocator; typedef xmlSAXLocator *xmlSAXLocatorPtr; typedef struct _xmlSAXHandler xmlSAXHandler; typedef xmlSAXHandler *xmlSAXHandlerPtr; /* entities.h */ typedef struct _xmlEntity xmlEntity; typedef xmlEntity *xmlEntityPtr; /** * BASE_BUFFER_SIZE: * * default buffer size 4000. */ #define BASE_BUFFER_SIZE 4096 /** * LIBXML_NAMESPACE_DICT: * * Defines experimental behaviour: * 1) xmlNs gets an additional field @context (a xmlDoc) * 2) when creating a tree, xmlNs->href is stored in the dict of xmlDoc. */ /* #define LIBXML_NAMESPACE_DICT */ /** * xmlBufferAllocationScheme: * * A buffer allocation scheme can be defined to either match exactly the * need or double it's allocated size each time it is found too small. */ typedef enum { XML_BUFFER_ALLOC_DOUBLEIT, /* double each time one need to grow */ XML_BUFFER_ALLOC_EXACT, /* grow only to the minimal size */ XML_BUFFER_ALLOC_IMMUTABLE, /* immutable buffer */ XML_BUFFER_ALLOC_IO, /* special allocation scheme used for I/O */ XML_BUFFER_ALLOC_HYBRID, /* exact up to a threshold, and doubleit thereafter */ XML_BUFFER_ALLOC_BOUNDED /* limit the upper size of the buffer */ } xmlBufferAllocationScheme; /** * xmlBuffer: * * A buffer structure, this old construct is limited to 2GB and * is being deprecated, use API with xmlBuf instead */ typedef struct _xmlBuffer xmlBuffer; typedef xmlBuffer *xmlBufferPtr; struct _xmlBuffer { xmlChar *content; /* The buffer content UTF8 */ unsigned int use; /* The buffer size used */ unsigned int size; /* The buffer size */ xmlBufferAllocationScheme alloc; /* The realloc method */ xmlChar *contentIO; /* in IO mode we may have a different base */ }; /** * xmlBuf: * * A buffer structure, new one, the actual structure internals are not public */ typedef struct _xmlBuf xmlBuf; /** * xmlBufPtr: * * A pointer to a buffer structure, the actual structure internals are not * public */ typedef xmlBuf *xmlBufPtr; /* * A few public routines for xmlBuf. As those are expected to be used * mostly internally the bulk of the routines are internal in buf.h */ XMLPUBFUN xmlChar* XMLCALL xmlBufContent (const xmlBuf* buf); XMLPUBFUN xmlChar* XMLCALL xmlBufEnd (xmlBufPtr buf); XMLPUBFUN size_t XMLCALL xmlBufUse (const xmlBufPtr buf); XMLPUBFUN size_t XMLCALL xmlBufShrink (xmlBufPtr buf, size_t len); /* * LIBXML2_NEW_BUFFER: * * Macro used to express that the API use the new buffers for * xmlParserInputBuffer and xmlOutputBuffer. The change was * introduced in 2.9.0. */ #define LIBXML2_NEW_BUFFER /** * XML_XML_NAMESPACE: * * This is the namespace for the special xml: prefix predefined in the * XML Namespace specification. */ #define XML_XML_NAMESPACE \ (const xmlChar *) "http://www.w3.org/XML/1998/namespace" /** * XML_XML_ID: * * This is the name for the special xml:id attribute */ #define XML_XML_ID (const xmlChar *) "xml:id" /* * The different element types carried by an XML tree. * * NOTE: This is synchronized with DOM Level1 values * See http://www.w3.org/TR/REC-DOM-Level-1/ * * Actually this had diverged a bit, and now XML_DOCUMENT_TYPE_NODE should * be deprecated to use an XML_DTD_NODE. */ typedef enum { XML_ELEMENT_NODE= 1, XML_ATTRIBUTE_NODE= 2, XML_TEXT_NODE= 3, XML_CDATA_SECTION_NODE= 4, XML_ENTITY_REF_NODE= 5, XML_ENTITY_NODE= 6, XML_PI_NODE= 7, XML_COMMENT_NODE= 8, XML_DOCUMENT_NODE= 9, XML_DOCUMENT_TYPE_NODE= 10, XML_DOCUMENT_FRAG_NODE= 11, XML_NOTATION_NODE= 12, XML_HTML_DOCUMENT_NODE= 13, XML_DTD_NODE= 14, XML_ELEMENT_DECL= 15, XML_ATTRIBUTE_DECL= 16, XML_ENTITY_DECL= 17, XML_NAMESPACE_DECL= 18, XML_XINCLUDE_START= 19, XML_XINCLUDE_END= 20 #ifdef LIBXML_DOCB_ENABLED ,XML_DOCB_DOCUMENT_NODE= 21 #endif } xmlElementType; /** * xmlNotation: * * A DTD Notation definition. */ typedef struct _xmlNotation xmlNotation; typedef xmlNotation *xmlNotationPtr; struct _xmlNotation { const xmlChar *name; /* Notation name */ const xmlChar *PublicID; /* Public identifier, if any */ const xmlChar *SystemID; /* System identifier, if any */ }; /** * xmlAttributeType: * * A DTD Attribute type definition. */ typedef enum { XML_ATTRIBUTE_CDATA = 1, XML_ATTRIBUTE_ID, XML_ATTRIBUTE_IDREF , XML_ATTRIBUTE_IDREFS, XML_ATTRIBUTE_ENTITY, XML_ATTRIBUTE_ENTITIES, XML_ATTRIBUTE_NMTOKEN, XML_ATTRIBUTE_NMTOKENS, XML_ATTRIBUTE_ENUMERATION, XML_ATTRIBUTE_NOTATION } xmlAttributeType; /** * xmlAttributeDefault: * * A DTD Attribute default definition. */ typedef enum { XML_ATTRIBUTE_NONE = 1, XML_ATTRIBUTE_REQUIRED, XML_ATTRIBUTE_IMPLIED, XML_ATTRIBUTE_FIXED } xmlAttributeDefault; /** * xmlEnumeration: * * List structure used when there is an enumeration in DTDs. */ typedef struct _xmlEnumeration xmlEnumeration; typedef xmlEnumeration *xmlEnumerationPtr; struct _xmlEnumeration { struct _xmlEnumeration *next; /* next one */ const xmlChar *name; /* Enumeration name */ }; /** * xmlAttribute: * * An Attribute declaration in a DTD. */ typedef struct _xmlAttribute xmlAttribute; typedef xmlAttribute *xmlAttributePtr; struct _xmlAttribute { void *_private; /* application data */ xmlElementType type; /* XML_ATTRIBUTE_DECL, must be second ! */ const xmlChar *name; /* Attribute name */ struct _xmlNode *children; /* NULL */ struct _xmlNode *last; /* NULL */ struct _xmlDtd *parent; /* -> DTD */ struct _xmlNode *next; /* next sibling link */ struct _xmlNode *prev; /* previous sibling link */ struct _xmlDoc *doc; /* the containing document */ struct _xmlAttribute *nexth; /* next in hash table */ xmlAttributeType atype; /* The attribute type */ xmlAttributeDefault def; /* the default */ const xmlChar *defaultValue; /* or the default value */ xmlEnumerationPtr tree; /* or the enumeration tree if any */ const xmlChar *prefix; /* the namespace prefix if any */ const xmlChar *elem; /* Element holding the attribute */ }; /** * xmlElementContentType: * * Possible definitions of element content types. */ typedef enum { XML_ELEMENT_CONTENT_PCDATA = 1, XML_ELEMENT_CONTENT_ELEMENT, XML_ELEMENT_CONTENT_SEQ, XML_ELEMENT_CONTENT_OR } xmlElementContentType; /** * xmlElementContentOccur: * * Possible definitions of element content occurrences. */ typedef enum { XML_ELEMENT_CONTENT_ONCE = 1, XML_ELEMENT_CONTENT_OPT, XML_ELEMENT_CONTENT_MULT, XML_ELEMENT_CONTENT_PLUS } xmlElementContentOccur; /** * xmlElementContent: * * An XML Element content as stored after parsing an element definition * in a DTD. */ typedef struct _xmlElementContent xmlElementContent; typedef xmlElementContent *xmlElementContentPtr; struct _xmlElementContent { xmlElementContentType type; /* PCDATA, ELEMENT, SEQ or OR */ xmlElementContentOccur ocur; /* ONCE, OPT, MULT or PLUS */ const xmlChar *name; /* Element name */ struct _xmlElementContent *c1; /* first child */ struct _xmlElementContent *c2; /* second child */ struct _xmlElementContent *parent; /* parent */ const xmlChar *prefix; /* Namespace prefix */ }; /** * xmlElementTypeVal: * * The different possibilities for an element content type. */ typedef enum { XML_ELEMENT_TYPE_UNDEFINED = 0, XML_ELEMENT_TYPE_EMPTY = 1, XML_ELEMENT_TYPE_ANY, XML_ELEMENT_TYPE_MIXED, XML_ELEMENT_TYPE_ELEMENT } xmlElementTypeVal; #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /** * xmlElement: * * An XML Element declaration from a DTD. */ typedef struct _xmlElement xmlElement; typedef xmlElement *xmlElementPtr; struct _xmlElement { void *_private; /* application data */ xmlElementType type; /* XML_ELEMENT_DECL, must be second ! */ const xmlChar *name; /* Element name */ struct _xmlNode *children; /* NULL */ struct _xmlNode *last; /* NULL */ struct _xmlDtd *parent; /* -> DTD */ struct _xmlNode *next; /* next sibling link */ struct _xmlNode *prev; /* previous sibling link */ struct _xmlDoc *doc; /* the containing document */ xmlElementTypeVal etype; /* The type */ xmlElementContentPtr content; /* the allowed element content */ xmlAttributePtr attributes; /* List of the declared attributes */ const xmlChar *prefix; /* the namespace prefix if any */ #ifdef LIBXML_REGEXP_ENABLED xmlRegexpPtr contModel; /* the validating regexp */ #else void *contModel; #endif }; /** * XML_LOCAL_NAMESPACE: * * A namespace declaration node. */ #define XML_LOCAL_NAMESPACE XML_NAMESPACE_DECL typedef xmlElementType xmlNsType; /** * xmlNs: * * An XML namespace. * Note that prefix == NULL is valid, it defines the default namespace * within the subtree (until overridden). * * xmlNsType is unified with xmlElementType. */ typedef struct _xmlNs xmlNs; typedef xmlNs *xmlNsPtr; struct _xmlNs { struct _xmlNs *next; /* next Ns link for this node */ xmlNsType type; /* global or local */ const xmlChar *href; /* URL for the namespace */ const xmlChar *prefix; /* prefix for the namespace */ void *_private; /* application data */ struct _xmlDoc *context; /* normally an xmlDoc */ }; /** * xmlDtd: * * An XML DTD, as defined by parent link */ struct _xmlNode *next; /* next sibling link */ struct _xmlNode *prev; /* previous sibling link */ struct _xmlDoc *doc; /* the containing document */ /* End of common part */ void *notations; /* Hash table for notations if any */ void *elements; /* Hash table for elements if any */ void *attributes; /* Hash table for attributes if any */ void *entities; /* Hash table for entities if any */ const xmlChar *ExternalID; /* External identifier for PUBLIC DTD */ const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC DTD */ void *pentities; /* Hash table for param entities if any */ }; /** * xmlAttr: * * An attribute on an XML node. */ typedef struct _xmlAttr xmlAttr; typedef xmlAttr *xmlAttrPtr; struct _xmlAttr { void *_private; /* application data */ xmlElementType type; /* XML_ATTRIBUTE_NODE, must be second ! */ const xmlChar *name; /* the name of the property */ struct _xmlNode *children; /* the value of the property */ struct _xmlNode *last; /* NULL */ struct _xmlNode *parent; /* child->parent link */ struct _xmlAttr *next; /* next sibling link */ struct _xmlAttr *prev; /* previous sibling link */ struct _xmlDoc *doc; /* the containing document */ xmlNs *ns; /* pointer to the associated namespace */ xmlAttributeType atype; /* the attribute type if validating */ void *psvi; /* for type/PSVI information */ }; /** * xmlID: * * An XML ID instance. */ typedef struct _xmlID xmlID; typedef xmlID *xmlIDPtr; struct _xmlID { struct _xmlID *next; /* next ID */ const xmlChar *value; /* The ID name */ xmlAttrPtr attr; /* The attribute holding it */ const xmlChar *name; /* The attribute if attr is not available */ int lineno; /* The line number if attr is not available */ struct _xmlDoc *doc; /* The document holding the ID */ }; /** * xmlRef: * * An XML IDREF instance. */ typedef struct _xmlRef xmlRef; typedef xmlRef *xmlRefPtr; struct _xmlRef { struct _xmlRef *next; /* next Ref */ const xmlChar *value; /* The Ref name */ xmlAttrPtr attr; /* The attribute holding it */ const xmlChar *name; /* The attribute if attr is not available */ int lineno; /* The line number if attr is not available */ }; /** * xmlNode: * * A node in an XML tree. */ typedef struct _xmlNode xmlNode; typedef xmlNode *xmlNodePtr; struct _xmlNode { void *_private; /* application data */ xmlElementType type; /* type number, must be second ! */ const xmlChar *name; /* the name of the node, or the entity */ struct _xmlNode *children; /* parent->childs link */ struct _xmlNode *last; /* last child link */ struct _xmlNode *parent; /* child->parent link */ struct _xmlNode *next; /* next sibling link */ struct _xmlNode *prev; /* previous sibling link */ struct _xmlDoc *doc; /* the containing document */ /* End of common part */ xmlNs *ns; /* pointer to the associated namespace */ xmlChar *content; /* the content */ struct _xmlAttr *properties;/* properties list */ xmlNs *nsDef; /* namespace definitions on this node */ void *psvi; /* for type/PSVI information */ unsigned short line; /* line number */ unsigned short extra; /* extra data for XPath/XSLT */ }; /** * XML_GET_CONTENT: * * Macro to extract the content pointer of a node. */ #define XML_GET_CONTENT(n) \ ((n)->type == XML_ELEMENT_NODE ? NULL : (n)->content) /** * XML_GET_LINE: * * Macro to extract the line number of an element node. */ #define XML_GET_LINE(n) \ (xmlGetLineNo(n)) /** * xmlDocProperty * * Set of properties of the document as found by the parser * Some of them are linked to similarly named xmlParserOption */ typedef enum { XML_DOC_WELLFORMED = 1<<0, /* document is XML well formed */ XML_DOC_NSVALID = 1<<1, /* document is Namespace valid */ XML_DOC_OLD10 = 1<<2, /* parsed with old XML-1.0 parser */ XML_DOC_DTDVALID = 1<<3, /* DTD validation was successful */ XML_DOC_XINCLUDE = 1<<4, /* XInclude substitution was done */ XML_DOC_USERBUILT = 1<<5, /* Document was built using the API and not by parsing an instance */ XML_DOC_INTERNAL = 1<<6, /* built for internal processing */ XML_DOC_HTML = 1<<7 /* parsed or built HTML document */ } xmlDocProperties; /** * xmlDoc: * * An XML document. */ typedef struct _xmlDoc xmlDoc; typedef xmlDoc *xmlDocPtr; struct _xmlDoc { void *_private; /* application data */ xmlElementType type; /* XML_DOCUMENT_NODE, must be second ! */ char *name; /* name/filename/URI of the document */ struct _xmlNode *children; /* the document tree */ struct _xmlNode *last; /* last child link */ struct _xmlNode *parent; /* child->parent link */ struct _xmlNode *next; /* next sibling link */ struct _xmlNode *prev; /* previous sibling link */ struct _xmlDoc *doc; /* autoreference to itself */ /* End of common part */ int compression;/* level of zlib compression */ int standalone; /* standalone document (no external refs) 1 if standalone="yes" 0 if standalone="no" -1 if there is no XML declaration -2 if there is an XML declaration, but no standalone attribute was specified */ struct _xmlDtd *intSubset; /* the document internal subset */ struct _xmlDtd *extSubset; /* the document external subset */ struct _xmlNs *oldNs; /* Global namespace, the old way */ const xmlChar *version; /* the XML version string */ const xmlChar *encoding; /* external initial encoding, if any */ void *ids; /* Hash table for ID attributes if any */ void *refs; /* Hash table for IDREFs attributes if any */ const xmlChar *URL; /* The URI for that document */ int charset; /* Internal flag for charset handling, actually an xmlCharEncoding */ struct _xmlDict *dict; /* dict used to allocate names or NULL */ void *psvi; /* for type/PSVI information */ int parseFlags; /* set of xmlParserOption used to parse the document */ int properties; /* set of xmlDocProperties for this document set at the end of parsing */ }; typedef struct _xmlDOMWrapCtxt xmlDOMWrapCtxt; typedef xmlDOMWrapCtxt *xmlDOMWrapCtxtPtr; /** * xmlDOMWrapAcquireNsFunction: * @ctxt: a DOM wrapper context * @node: the context node (element or attribute) * @nsName: the requested namespace name * @nsPrefix: the requested namespace prefix * * A function called to acquire namespaces (xmlNs) from the wrapper. * * Returns an xmlNsPtr or NULL in case of an error. */ typedef xmlNsPtr (*xmlDOMWrapAcquireNsFunction) (xmlDOMWrapCtxtPtr ctxt, xmlNodePtr node, const xmlChar *nsName, const xmlChar *nsPrefix); /** * xmlDOMWrapCtxt: * * Context for DOM wrapper-operations. */ struct _xmlDOMWrapCtxt { void * _private; /* * The type of this context, just in case we need specialized * contexts in the future. */ int type; /* * Internal namespace map used for various operations. */ void * namespaceMap; /* * Use this one to acquire an xmlNsPtr intended for node->ns. * (Note that this is not intended for elem->nsDef). */ xmlDOMWrapAcquireNsFunction getNsForNodeFunc; }; /** * xmlChildrenNode: * * Macro for compatibility naming layer with libxml1. Maps * to "children." */ #ifndef xmlChildrenNode #define xmlChildrenNode children #endif /** * xmlRootNode: * * Macro for compatibility naming layer with libxml1. Maps * to "children". */ #ifndef xmlRootNode #define xmlRootNode children #endif /* * Variables. */ /* * Some helper functions */ #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_DEBUG_ENABLED) || \ defined (LIBXML_HTML_ENABLED) || defined(LIBXML_SAX1_ENABLED) || \ defined(LIBXML_HTML_ENABLED) || defined(LIBXML_WRITER_ENABLED) || \ defined(LIBXML_DOCB_ENABLED) || defined(LIBXML_LEGACY_ENABLED) XMLPUBFUN int XMLCALL xmlValidateNCName (const xmlChar *value, int space); #endif #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN int XMLCALL xmlValidateQName (const xmlChar *value, int space); XMLPUBFUN int XMLCALL xmlValidateName (const xmlChar *value, int space); XMLPUBFUN int XMLCALL xmlValidateNMToken (const xmlChar *value, int space); #endif XMLPUBFUN xmlChar * XMLCALL xmlBuildQName (const xmlChar *ncname, const xmlChar *prefix, xmlChar *memory, int len); XMLPUBFUN xmlChar * XMLCALL xmlSplitQName2 (const xmlChar *name, xmlChar **prefix); XMLPUBFUN const xmlChar * XMLCALL xmlSplitQName3 (const xmlChar *name, int *len); /* * Handling Buffers, the old ones see @xmlBuf for the new ones. */ XMLPUBFUN void XMLCALL xmlSetBufferAllocationScheme(xmlBufferAllocationScheme scheme); XMLPUBFUN xmlBufferAllocationScheme XMLCALL xmlGetBufferAllocationScheme(void); XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreate (void); XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreateSize (size_t size); XMLPUBFUN xmlBufferPtr XMLCALL xmlBufferCreateStatic (void *mem, size_t size); XMLPUBFUN int XMLCALL xmlBufferResize (xmlBufferPtr buf, unsigned int size); XMLPUBFUN void XMLCALL xmlBufferFree (xmlBufferPtr buf); XMLPUBFUN int XMLCALL xmlBufferDump (FILE *file, xmlBufferPtr buf); XMLPUBFUN int XMLCALL xmlBufferAdd (xmlBufferPtr buf, const xmlChar *str, int len); XMLPUBFUN int XMLCALL xmlBufferAddHead (xmlBufferPtr buf, const xmlChar *str, int len); XMLPUBFUN int XMLCALL xmlBufferCat (xmlBufferPtr buf, const xmlChar *str); XMLPUBFUN int XMLCALL xmlBufferCCat (xmlBufferPtr buf, const char *str); XMLPUBFUN int XMLCALL xmlBufferShrink (xmlBufferPtr buf, unsigned int len); XMLPUBFUN int XMLCALL xmlBufferGrow (xmlBufferPtr buf, unsigned int len); XMLPUBFUN void XMLCALL xmlBufferEmpty (xmlBufferPtr buf); XMLPUBFUN const xmlChar* XMLCALL xmlBufferContent (const xmlBuffer *buf); XMLPUBFUN xmlChar* XMLCALL xmlBufferDetach (xmlBufferPtr buf); XMLPUBFUN void XMLCALL xmlBufferSetAllocationScheme(xmlBufferPtr buf, xmlBufferAllocationScheme scheme); XMLPUBFUN int XMLCALL xmlBufferLength (const xmlBuffer *buf); /* * Creating/freeing new structures. */ XMLPUBFUN xmlDtdPtr XMLCALL xmlCreateIntSubset (xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN xmlDtdPtr XMLCALL xmlNewDtd (xmlDocPtr doc, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN xmlDtdPtr XMLCALL xmlGetIntSubset (const xmlDoc *doc); XMLPUBFUN void XMLCALL xmlFreeDtd (xmlDtdPtr cur); #ifdef LIBXML_LEGACY_ENABLED XMLPUBFUN xmlNsPtr XMLCALL xmlNewGlobalNs (xmlDocPtr doc, const xmlChar *href, const xmlChar *prefix); #endif /* LIBXML_LEGACY_ENABLED */ XMLPUBFUN xmlNsPtr XMLCALL xmlNewNs (xmlNodePtr node, const xmlChar *href, const xmlChar *prefix); XMLPUBFUN void XMLCALL xmlFreeNs (xmlNsPtr cur); XMLPUBFUN void XMLCALL xmlFreeNsList (xmlNsPtr cur); XMLPUBFUN xmlDocPtr XMLCALL xmlNewDoc (const xmlChar *version); XMLPUBFUN void XMLCALL xmlFreeDoc (xmlDocPtr cur); XMLPUBFUN xmlAttrPtr XMLCALL xmlNewDocProp (xmlDocPtr doc, const xmlChar *name, const xmlChar *value); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN xmlAttrPtr XMLCALL xmlNewProp (xmlNodePtr node, const xmlChar *name, const xmlChar *value); #endif XMLPUBFUN xmlAttrPtr XMLCALL xmlNewNsProp (xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, const xmlChar *value); XMLPUBFUN xmlAttrPtr XMLCALL xmlNewNsPropEatName (xmlNodePtr node, xmlNsPtr ns, xmlChar *name, const xmlChar *value); XMLPUBFUN void XMLCALL xmlFreePropList (xmlAttrPtr cur); XMLPUBFUN void XMLCALL xmlFreeProp (xmlAttrPtr cur); XMLPUBFUN xmlAttrPtr XMLCALL xmlCopyProp (xmlNodePtr target, xmlAttrPtr cur); XMLPUBFUN xmlAttrPtr XMLCALL xmlCopyPropList (xmlNodePtr target, xmlAttrPtr cur); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlDtdPtr XMLCALL xmlCopyDtd (xmlDtdPtr dtd); #endif /* LIBXML_TREE_ENABLED */ #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN xmlDocPtr XMLCALL xmlCopyDoc (xmlDocPtr doc, int recursive); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */ /* * Creating new nodes. */ XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNode (xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocNodeEatName (xmlDocPtr doc, xmlNsPtr ns, xmlChar *name, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewNode (xmlNsPtr ns, const xmlChar *name); XMLPUBFUN xmlNodePtr XMLCALL xmlNewNodeEatName (xmlNsPtr ns, xmlChar *name); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN xmlNodePtr XMLCALL xmlNewChild (xmlNodePtr parent, xmlNsPtr ns, const xmlChar *name, const xmlChar *content); #endif XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocText (const xmlDoc *doc, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewText (const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocPI (xmlDocPtr doc, const xmlChar *name, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewPI (const xmlChar *name, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocTextLen (xmlDocPtr doc, const xmlChar *content, int len); XMLPUBFUN xmlNodePtr XMLCALL xmlNewTextLen (const xmlChar *content, int len); XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocComment (xmlDocPtr doc, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewComment (const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewCDataBlock (xmlDocPtr doc, const xmlChar *content, int len); XMLPUBFUN xmlNodePtr XMLCALL xmlNewCharRef (xmlDocPtr doc, const xmlChar *name); XMLPUBFUN xmlNodePtr XMLCALL xmlNewReference (const xmlDoc *doc, const xmlChar *name); XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNode (xmlNodePtr node, int recursive); XMLPUBFUN xmlNodePtr XMLCALL xmlDocCopyNode (xmlNodePtr node, xmlDocPtr doc, int recursive); XMLPUBFUN xmlNodePtr XMLCALL xmlDocCopyNodeList (xmlDocPtr doc, xmlNodePtr node); XMLPUBFUN xmlNodePtr XMLCALL xmlCopyNodeList (xmlNodePtr node); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlNodePtr XMLCALL xmlNewTextChild (xmlNodePtr parent, xmlNsPtr ns, const xmlChar *name, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocRawNode (xmlDocPtr doc, xmlNsPtr ns, const xmlChar *name, const xmlChar *content); XMLPUBFUN xmlNodePtr XMLCALL xmlNewDocFragment (xmlDocPtr doc); #endif /* LIBXML_TREE_ENABLED */ /* * Navigating. */ XMLPUBFUN long XMLCALL xmlGetLineNo (const xmlNode *node); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) XMLPUBFUN xmlChar * XMLCALL xmlGetNodePath (const xmlNode *node); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_DEBUG_ENABLED) */ XMLPUBFUN xmlNodePtr XMLCALL xmlDocGetRootElement (const xmlDoc *doc); XMLPUBFUN xmlNodePtr XMLCALL xmlGetLastChild (const xmlNode *parent); XMLPUBFUN int XMLCALL xmlNodeIsText (const xmlNode *node); XMLPUBFUN int XMLCALL xmlIsBlankNode (const xmlNode *node); /* * Changing the structure. */ #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) XMLPUBFUN xmlNodePtr XMLCALL xmlDocSetRootElement (xmlDocPtr doc, xmlNodePtr root); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */ #ifdef LIBXML_TREE_ENABLED XMLPUBFUN void XMLCALL xmlNodeSetName (xmlNodePtr cur, const xmlChar *name); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN xmlNodePtr XMLCALL xmlAddChild (xmlNodePtr parent, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlAddChildList (xmlNodePtr parent, xmlNodePtr cur); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) XMLPUBFUN xmlNodePtr XMLCALL xmlReplaceNode (xmlNodePtr old, xmlNodePtr cur); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_WRITER_ENABLED) */ #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) XMLPUBFUN xmlNodePtr XMLCALL xmlAddPrevSibling (xmlNodePtr cur, xmlNodePtr elem); #endif /* LIBXML_TREE_ENABLED || LIBXML_HTML_ENABLED || LIBXML_SCHEMAS_ENABLED */ XMLPUBFUN xmlNodePtr XMLCALL xmlAddSibling (xmlNodePtr cur, xmlNodePtr elem); XMLPUBFUN xmlNodePtr XMLCALL xmlAddNextSibling (xmlNodePtr cur, xmlNodePtr elem); XMLPUBFUN void XMLCALL xmlUnlinkNode (xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlTextMerge (xmlNodePtr first, xmlNodePtr second); XMLPUBFUN int XMLCALL xmlTextConcat (xmlNodePtr node, const xmlChar *content, int len); XMLPUBFUN void XMLCALL xmlFreeNodeList (xmlNodePtr cur); XMLPUBFUN void XMLCALL xmlFreeNode (xmlNodePtr cur); XMLPUBFUN void XMLCALL xmlSetTreeDoc (xmlNodePtr tree, xmlDocPtr doc); XMLPUBFUN void XMLCALL xmlSetListDoc (xmlNodePtr list, xmlDocPtr doc); /* * Namespaces. */ XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNs (xmlDocPtr doc, xmlNodePtr node, const xmlChar *nameSpace); XMLPUBFUN xmlNsPtr XMLCALL xmlSearchNsByHref (xmlDocPtr doc, xmlNodePtr node, const xmlChar *href); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN xmlNsPtr * XMLCALL xmlGetNsList (const xmlDoc *doc, const xmlNode *node); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XPATH_ENABLED) */ XMLPUBFUN void XMLCALL xmlSetNs (xmlNodePtr node, xmlNsPtr ns); XMLPUBFUN xmlNsPtr XMLCALL xmlCopyNamespace (xmlNsPtr cur); XMLPUBFUN xmlNsPtr XMLCALL xmlCopyNamespaceList (xmlNsPtr cur); /* * Changing the content. */ #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) XMLPUBFUN xmlAttrPtr XMLCALL xmlSetProp (xmlNodePtr node, const xmlChar *name, const xmlChar *value); XMLPUBFUN xmlAttrPtr XMLCALL xmlSetNsProp (xmlNodePtr node, xmlNsPtr ns, const xmlChar *name, const xmlChar *value); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) || \ defined(LIBXML_SCHEMAS_ENABLED) || defined(LIBXML_HTML_ENABLED) */ XMLPUBFUN xmlChar * XMLCALL xmlGetNoNsProp (const xmlNode *node, const xmlChar *name); XMLPUBFUN xmlChar * XMLCALL xmlGetProp (const xmlNode *node, const xmlChar *name); XMLPUBFUN xmlAttrPtr XMLCALL xmlHasProp (const xmlNode *node, const xmlChar *name); XMLPUBFUN xmlAttrPtr XMLCALL xmlHasNsProp (const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace); XMLPUBFUN xmlChar * XMLCALL xmlGetNsProp (const xmlNode *node, const xmlChar *name, const xmlChar *nameSpace); XMLPUBFUN xmlNodePtr XMLCALL xmlStringGetNodeList (const xmlDoc *doc, const xmlChar *value); XMLPUBFUN xmlNodePtr XMLCALL xmlStringLenGetNodeList (const xmlDoc *doc, const xmlChar *value, int len); XMLPUBFUN xmlChar * XMLCALL xmlNodeListGetString (xmlDocPtr doc, const xmlNode *list, int inLine); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlChar * XMLCALL xmlNodeListGetRawString (const xmlDoc *doc, const xmlNode *list, int inLine); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN void XMLCALL xmlNodeSetContent (xmlNodePtr cur, const xmlChar *content); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN void XMLCALL xmlNodeSetContentLen (xmlNodePtr cur, const xmlChar *content, int len); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN void XMLCALL xmlNodeAddContent (xmlNodePtr cur, const xmlChar *content); XMLPUBFUN void XMLCALL xmlNodeAddContentLen (xmlNodePtr cur, const xmlChar *content, int len); XMLPUBFUN xmlChar * XMLCALL xmlNodeGetContent (const xmlNode *cur); XMLPUBFUN int XMLCALL xmlNodeBufGetContent (xmlBufferPtr buffer, const xmlNode *cur); XMLPUBFUN int XMLCALL xmlBufGetNodeContent (xmlBufPtr buf, const xmlNode *cur); XMLPUBFUN xmlChar * XMLCALL xmlNodeGetLang (const xmlNode *cur); XMLPUBFUN int XMLCALL xmlNodeGetSpacePreserve (const xmlNode *cur); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN void XMLCALL xmlNodeSetLang (xmlNodePtr cur, const xmlChar *lang); XMLPUBFUN void XMLCALL xmlNodeSetSpacePreserve (xmlNodePtr cur, int val); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN xmlChar * XMLCALL xmlNodeGetBase (const xmlDoc *doc, const xmlNode *cur); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_XINCLUDE_ENABLED) XMLPUBFUN void XMLCALL xmlNodeSetBase (xmlNodePtr cur, const xmlChar *uri); #endif /* * Removing content. */ XMLPUBFUN int XMLCALL xmlRemoveProp (xmlAttrPtr cur); #if defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN int XMLCALL xmlUnsetNsProp (xmlNodePtr node, xmlNsPtr ns, const xmlChar *name); XMLPUBFUN int XMLCALL xmlUnsetProp (xmlNodePtr node, const xmlChar *name); #endif /* defined(LIBXML_TREE_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) */ /* * Internal, don't use. */ XMLPUBFUN void XMLCALL xmlBufferWriteCHAR (xmlBufferPtr buf, const xmlChar *string); XMLPUBFUN void XMLCALL xmlBufferWriteChar (xmlBufferPtr buf, const char *string); XMLPUBFUN void XMLCALL xmlBufferWriteQuotedString(xmlBufferPtr buf, const xmlChar *string); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void xmlAttrSerializeTxtContent(xmlBufferPtr buf, xmlDocPtr doc, xmlAttrPtr attr, const xmlChar *string); #endif /* LIBXML_OUTPUT_ENABLED */ #ifdef LIBXML_TREE_ENABLED /* * Namespace handling. */ XMLPUBFUN int XMLCALL xmlReconciliateNs (xmlDocPtr doc, xmlNodePtr tree); #endif #ifdef LIBXML_OUTPUT_ENABLED /* * Saving. */ XMLPUBFUN void XMLCALL xmlDocDumpFormatMemory (xmlDocPtr cur, xmlChar **mem, int *size, int format); XMLPUBFUN void XMLCALL xmlDocDumpMemory (xmlDocPtr cur, xmlChar **mem, int *size); XMLPUBFUN void XMLCALL xmlDocDumpMemoryEnc (xmlDocPtr out_doc, xmlChar **doc_txt_ptr, int * doc_txt_len, const char *txt_encoding); XMLPUBFUN void XMLCALL xmlDocDumpFormatMemoryEnc(xmlDocPtr out_doc, xmlChar **doc_txt_ptr, int * doc_txt_len, const char *txt_encoding, int format); XMLPUBFUN int XMLCALL xmlDocFormatDump (FILE *f, xmlDocPtr cur, int format); XMLPUBFUN int XMLCALL xmlDocDump (FILE *f, xmlDocPtr cur); XMLPUBFUN void XMLCALL xmlElemDump (FILE *f, xmlDocPtr doc, xmlNodePtr cur); XMLPUBFUN int XMLCALL xmlSaveFile (const char *filename, xmlDocPtr cur); XMLPUBFUN int XMLCALL xmlSaveFormatFile (const char *filename, xmlDocPtr cur, int format); XMLPUBFUN size_t XMLCALL xmlBufNodeDump (xmlBufPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format); XMLPUBFUN int XMLCALL xmlNodeDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format); XMLPUBFUN int XMLCALL xmlSaveFileTo (xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding); XMLPUBFUN int XMLCALL xmlSaveFormatFileTo (xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding, int format); XMLPUBFUN void XMLCALL xmlNodeDumpOutput (xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, int level, int format, const char *encoding); XMLPUBFUN int XMLCALL xmlSaveFormatFileEnc (const char *filename, xmlDocPtr cur, const char *encoding, int format); XMLPUBFUN int XMLCALL xmlSaveFileEnc (const char *filename, xmlDocPtr cur, const char *encoding); #endif /* LIBXML_OUTPUT_ENABLED */ /* * XHTML */ XMLPUBFUN int XMLCALL xmlIsXHTML (const xmlChar *systemID, const xmlChar *publicID); /* * Compression. */ XMLPUBFUN int XMLCALL xmlGetDocCompressMode (const xmlDoc *doc); XMLPUBFUN void XMLCALL xmlSetDocCompressMode (xmlDocPtr doc, int mode); XMLPUBFUN int XMLCALL xmlGetCompressMode (void); XMLPUBFUN void XMLCALL xmlSetCompressMode (int mode); /* * DOM-wrapper helper functions. */ XMLPUBFUN xmlDOMWrapCtxtPtr XMLCALL xmlDOMWrapNewCtxt (void); XMLPUBFUN void XMLCALL xmlDOMWrapFreeCtxt (xmlDOMWrapCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlDOMWrapReconcileNamespaces(xmlDOMWrapCtxtPtr ctxt, xmlNodePtr elem, int options); XMLPUBFUN int XMLCALL xmlDOMWrapAdoptNode (xmlDOMWrapCtxtPtr ctxt, xmlDocPtr sourceDoc, xmlNodePtr node, xmlDocPtr destDoc, xmlNodePtr destParent, int options); XMLPUBFUN int XMLCALL xmlDOMWrapRemoveNode (xmlDOMWrapCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr node, int options); XMLPUBFUN int XMLCALL xmlDOMWrapCloneNode (xmlDOMWrapCtxtPtr ctxt, xmlDocPtr sourceDoc, xmlNodePtr node, xmlNodePtr *clonedNode, xmlDocPtr destDoc, xmlNodePtr destParent, int deep, int options); #ifdef LIBXML_TREE_ENABLED /* * 5 interfaces from DOM ElementTraversal, but different in entities * traversal. */ XMLPUBFUN unsigned long XMLCALL xmlChildElementCount (xmlNodePtr parent); XMLPUBFUN xmlNodePtr XMLCALL xmlNextElementSibling (xmlNodePtr node); XMLPUBFUN xmlNodePtr XMLCALL xmlFirstElementChild (xmlNodePtr parent); XMLPUBFUN xmlNodePtr XMLCALL xmlLastElementChild (xmlNodePtr parent); XMLPUBFUN xmlNodePtr XMLCALL xmlPreviousElementSibling (xmlNodePtr node); #endif #ifdef __cplusplus } #endif #ifndef __XML_PARSER_H__ #include #endif #endif /* __XML_TREE_H__ */ PK!e  libxml/list.hnu[/* * Summary: lists interfaces * Description: this module implement the list support used in * various place in the library. * * Copy: See Copyright for the status of this software. * * Author: Gary Pennington */ #ifndef __XML_LINK_INCLUDE__ #define __XML_LINK_INCLUDE__ #include #ifdef __cplusplus extern "C" { #endif typedef struct _xmlLink xmlLink; typedef xmlLink *xmlLinkPtr; typedef struct _xmlList xmlList; typedef xmlList *xmlListPtr; /** * xmlListDeallocator: * @lk: the data to deallocate * * Callback function used to free data from a list. */ typedef void (*xmlListDeallocator) (xmlLinkPtr lk); /** * xmlListDataCompare: * @data0: the first data * @data1: the second data * * Callback function used to compare 2 data. * * Returns 0 is equality, -1 or 1 otherwise depending on the ordering. */ typedef int (*xmlListDataCompare) (const void *data0, const void *data1); /** * xmlListWalker: * @data: the data found in the list * @user: extra user provided data to the walker * * Callback function used when walking a list with xmlListWalk(). * * Returns 0 to stop walking the list, 1 otherwise. */ typedef int (*xmlListWalker) (const void *data, void *user); /* Creation/Deletion */ XMLPUBFUN xmlListPtr XMLCALL xmlListCreate (xmlListDeallocator deallocator, xmlListDataCompare compare); XMLPUBFUN void XMLCALL xmlListDelete (xmlListPtr l); /* Basic Operators */ XMLPUBFUN void * XMLCALL xmlListSearch (xmlListPtr l, void *data); XMLPUBFUN void * XMLCALL xmlListReverseSearch (xmlListPtr l, void *data); XMLPUBFUN int XMLCALL xmlListInsert (xmlListPtr l, void *data) ; XMLPUBFUN int XMLCALL xmlListAppend (xmlListPtr l, void *data) ; XMLPUBFUN int XMLCALL xmlListRemoveFirst (xmlListPtr l, void *data); XMLPUBFUN int XMLCALL xmlListRemoveLast (xmlListPtr l, void *data); XMLPUBFUN int XMLCALL xmlListRemoveAll (xmlListPtr l, void *data); XMLPUBFUN void XMLCALL xmlListClear (xmlListPtr l); XMLPUBFUN int XMLCALL xmlListEmpty (xmlListPtr l); XMLPUBFUN xmlLinkPtr XMLCALL xmlListFront (xmlListPtr l); XMLPUBFUN xmlLinkPtr XMLCALL xmlListEnd (xmlListPtr l); XMLPUBFUN int XMLCALL xmlListSize (xmlListPtr l); XMLPUBFUN void XMLCALL xmlListPopFront (xmlListPtr l); XMLPUBFUN void XMLCALL xmlListPopBack (xmlListPtr l); XMLPUBFUN int XMLCALL xmlListPushFront (xmlListPtr l, void *data); XMLPUBFUN int XMLCALL xmlListPushBack (xmlListPtr l, void *data); /* Advanced Operators */ XMLPUBFUN void XMLCALL xmlListReverse (xmlListPtr l); XMLPUBFUN void XMLCALL xmlListSort (xmlListPtr l); XMLPUBFUN void XMLCALL xmlListWalk (xmlListPtr l, xmlListWalker walker, void *user); XMLPUBFUN void XMLCALL xmlListReverseWalk (xmlListPtr l, xmlListWalker walker, void *user); XMLPUBFUN void XMLCALL xmlListMerge (xmlListPtr l1, xmlListPtr l2); XMLPUBFUN xmlListPtr XMLCALL xmlListDup (const xmlListPtr old); XMLPUBFUN int XMLCALL xmlListCopy (xmlListPtr cur, const xmlListPtr old); /* Link operators */ XMLPUBFUN void * XMLCALL xmlLinkGetData (xmlLinkPtr lk); /* xmlListUnique() */ /* xmlListSwap */ #ifdef __cplusplus } #endif #endif /* __XML_LINK_INCLUDE__ */ PK!8\U U libxml/DOCBparser.hnu[/* * Summary: old DocBook SGML parser * Description: interface for a DocBook SGML non-verifying parser * This code is DEPRECATED, and should not be used anymore. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __DOCB_PARSER_H__ #define __DOCB_PARSER_H__ #include #ifdef LIBXML_DOCB_ENABLED #include #include #ifndef IN_LIBXML #ifdef __GNUC__ #warning "The DOCBparser module has been deprecated in libxml2-2.6.0" #endif #endif #ifdef __cplusplus extern "C" { #endif /* * Most of the back-end structures from XML and SGML are shared. */ typedef xmlParserCtxt docbParserCtxt; typedef xmlParserCtxtPtr docbParserCtxtPtr; typedef xmlSAXHandler docbSAXHandler; typedef xmlSAXHandlerPtr docbSAXHandlerPtr; typedef xmlParserInput docbParserInput; typedef xmlParserInputPtr docbParserInputPtr; typedef xmlDocPtr docbDocPtr; /* * There is only few public functions. */ XMLPUBFUN int XMLCALL docbEncodeEntities(unsigned char *out, int *outlen, const unsigned char *in, int *inlen, int quoteChar); XMLPUBFUN docbDocPtr XMLCALL docbSAXParseDoc (xmlChar *cur, const char *encoding, docbSAXHandlerPtr sax, void *userData); XMLPUBFUN docbDocPtr XMLCALL docbParseDoc (xmlChar *cur, const char *encoding); XMLPUBFUN docbDocPtr XMLCALL docbSAXParseFile (const char *filename, const char *encoding, docbSAXHandlerPtr sax, void *userData); XMLPUBFUN docbDocPtr XMLCALL docbParseFile (const char *filename, const char *encoding); /** * Interfaces for the Push mode. */ XMLPUBFUN void XMLCALL docbFreeParserCtxt (docbParserCtxtPtr ctxt); XMLPUBFUN docbParserCtxtPtr XMLCALL docbCreatePushParserCtxt(docbSAXHandlerPtr sax, void *user_data, const char *chunk, int size, const char *filename, xmlCharEncoding enc); XMLPUBFUN int XMLCALL docbParseChunk (docbParserCtxtPtr ctxt, const char *chunk, int size, int terminate); XMLPUBFUN docbParserCtxtPtr XMLCALL docbCreateFileParserCtxt(const char *filename, const char *encoding); XMLPUBFUN int XMLCALL docbParseDocument (docbParserCtxtPtr ctxt); #ifdef __cplusplus } #endif #endif /* LIBXML_DOCB_ENABLED */ #endif /* __DOCB_PARSER_H__ */ PK!@hԇlibxml/xmlstring.hnu[/* * Summary: set of routines to process strings * Description: type and interfaces needed for the internal string handling * of the library, especially UTF8 processing. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_STRING_H__ #define __XML_STRING_H__ #include #include #ifdef __cplusplus extern "C" { #endif /** * xmlChar: * * This is a basic byte in an UTF-8 encoded string. * It's unsigned allowing to pinpoint case where char * are assigned * to xmlChar * (possibly making serialization back impossible). */ typedef unsigned char xmlChar; /** * BAD_CAST: * * Macro to cast a string to an xmlChar * when one know its safe. */ #define BAD_CAST (xmlChar *) /* * xmlChar handling */ XMLPUBFUN xmlChar * XMLCALL xmlStrdup (const xmlChar *cur); XMLPUBFUN xmlChar * XMLCALL xmlStrndup (const xmlChar *cur, int len); XMLPUBFUN xmlChar * XMLCALL xmlCharStrndup (const char *cur, int len); XMLPUBFUN xmlChar * XMLCALL xmlCharStrdup (const char *cur); XMLPUBFUN xmlChar * XMLCALL xmlStrsub (const xmlChar *str, int start, int len); XMLPUBFUN const xmlChar * XMLCALL xmlStrchr (const xmlChar *str, xmlChar val); XMLPUBFUN const xmlChar * XMLCALL xmlStrstr (const xmlChar *str, const xmlChar *val); XMLPUBFUN const xmlChar * XMLCALL xmlStrcasestr (const xmlChar *str, const xmlChar *val); XMLPUBFUN int XMLCALL xmlStrcmp (const xmlChar *str1, const xmlChar *str2); XMLPUBFUN int XMLCALL xmlStrncmp (const xmlChar *str1, const xmlChar *str2, int len); XMLPUBFUN int XMLCALL xmlStrcasecmp (const xmlChar *str1, const xmlChar *str2); XMLPUBFUN int XMLCALL xmlStrncasecmp (const xmlChar *str1, const xmlChar *str2, int len); XMLPUBFUN int XMLCALL xmlStrEqual (const xmlChar *str1, const xmlChar *str2); XMLPUBFUN int XMLCALL xmlStrQEqual (const xmlChar *pref, const xmlChar *name, const xmlChar *str); XMLPUBFUN int XMLCALL xmlStrlen (const xmlChar *str); XMLPUBFUN xmlChar * XMLCALL xmlStrcat (xmlChar *cur, const xmlChar *add); XMLPUBFUN xmlChar * XMLCALL xmlStrncat (xmlChar *cur, const xmlChar *add, int len); XMLPUBFUN xmlChar * XMLCALL xmlStrncatNew (const xmlChar *str1, const xmlChar *str2, int len); XMLPUBFUN int XMLCALL xmlStrPrintf (xmlChar *buf, int len, const char *msg, ...) LIBXML_ATTR_FORMAT(3,4); XMLPUBFUN int XMLCALL xmlStrVPrintf (xmlChar *buf, int len, const char *msg, va_list ap) LIBXML_ATTR_FORMAT(3,0); XMLPUBFUN int XMLCALL xmlGetUTF8Char (const unsigned char *utf, int *len); XMLPUBFUN int XMLCALL xmlCheckUTF8 (const unsigned char *utf); XMLPUBFUN int XMLCALL xmlUTF8Strsize (const xmlChar *utf, int len); XMLPUBFUN xmlChar * XMLCALL xmlUTF8Strndup (const xmlChar *utf, int len); XMLPUBFUN const xmlChar * XMLCALL xmlUTF8Strpos (const xmlChar *utf, int pos); XMLPUBFUN int XMLCALL xmlUTF8Strloc (const xmlChar *utf, const xmlChar *utfchar); XMLPUBFUN xmlChar * XMLCALL xmlUTF8Strsub (const xmlChar *utf, int start, int len); XMLPUBFUN int XMLCALL xmlUTF8Strlen (const xmlChar *utf); XMLPUBFUN int XMLCALL xmlUTF8Size (const xmlChar *utf); XMLPUBFUN int XMLCALL xmlUTF8Charcmp (const xmlChar *utf1, const xmlChar *utf2); #ifdef __cplusplus } #endif #endif /* __XML_STRING_H__ */ PK!6(UU libxml/SAX2.hnu[/* * Summary: SAX2 parser interface used to build the DOM tree * Description: those are the default SAX2 interfaces used by * the library when building DOM tree. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_SAX2_H__ #define __XML_SAX2_H__ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif XMLPUBFUN const xmlChar * XMLCALL xmlSAX2GetPublicId (void *ctx); XMLPUBFUN const xmlChar * XMLCALL xmlSAX2GetSystemId (void *ctx); XMLPUBFUN void XMLCALL xmlSAX2SetDocumentLocator (void *ctx, xmlSAXLocatorPtr loc); XMLPUBFUN int XMLCALL xmlSAX2GetLineNumber (void *ctx); XMLPUBFUN int XMLCALL xmlSAX2GetColumnNumber (void *ctx); XMLPUBFUN int XMLCALL xmlSAX2IsStandalone (void *ctx); XMLPUBFUN int XMLCALL xmlSAX2HasInternalSubset (void *ctx); XMLPUBFUN int XMLCALL xmlSAX2HasExternalSubset (void *ctx); XMLPUBFUN void XMLCALL xmlSAX2InternalSubset (void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN void XMLCALL xmlSAX2ExternalSubset (void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN xmlEntityPtr XMLCALL xmlSAX2GetEntity (void *ctx, const xmlChar *name); XMLPUBFUN xmlEntityPtr XMLCALL xmlSAX2GetParameterEntity (void *ctx, const xmlChar *name); XMLPUBFUN xmlParserInputPtr XMLCALL xmlSAX2ResolveEntity (void *ctx, const xmlChar *publicId, const xmlChar *systemId); XMLPUBFUN void XMLCALL xmlSAX2EntityDecl (void *ctx, const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content); XMLPUBFUN void XMLCALL xmlSAX2AttributeDecl (void *ctx, const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree); XMLPUBFUN void XMLCALL xmlSAX2ElementDecl (void *ctx, const xmlChar *name, int type, xmlElementContentPtr content); XMLPUBFUN void XMLCALL xmlSAX2NotationDecl (void *ctx, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId); XMLPUBFUN void XMLCALL xmlSAX2UnparsedEntityDecl (void *ctx, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName); XMLPUBFUN void XMLCALL xmlSAX2StartDocument (void *ctx); XMLPUBFUN void XMLCALL xmlSAX2EndDocument (void *ctx); #if defined(LIBXML_SAX1_ENABLED) || defined(LIBXML_HTML_ENABLED) || \ defined(LIBXML_WRITER_ENABLED) || defined(LIBXML_DOCB_ENABLED) || \ defined(LIBXML_LEGACY_ENABLED) XMLPUBFUN void XMLCALL xmlSAX2StartElement (void *ctx, const xmlChar *fullname, const xmlChar **atts); XMLPUBFUN void XMLCALL xmlSAX2EndElement (void *ctx, const xmlChar *name); #endif /* LIBXML_SAX1_ENABLED or LIBXML_HTML_ENABLED or LIBXML_LEGACY_ENABLED */ XMLPUBFUN void XMLCALL xmlSAX2StartElementNs (void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes); XMLPUBFUN void XMLCALL xmlSAX2EndElementNs (void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI); XMLPUBFUN void XMLCALL xmlSAX2Reference (void *ctx, const xmlChar *name); XMLPUBFUN void XMLCALL xmlSAX2Characters (void *ctx, const xmlChar *ch, int len); XMLPUBFUN void XMLCALL xmlSAX2IgnorableWhitespace (void *ctx, const xmlChar *ch, int len); XMLPUBFUN void XMLCALL xmlSAX2ProcessingInstruction (void *ctx, const xmlChar *target, const xmlChar *data); XMLPUBFUN void XMLCALL xmlSAX2Comment (void *ctx, const xmlChar *value); XMLPUBFUN void XMLCALL xmlSAX2CDataBlock (void *ctx, const xmlChar *value, int len); #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN int XMLCALL xmlSAXDefaultVersion (int version); #endif /* LIBXML_SAX1_ENABLED */ XMLPUBFUN int XMLCALL xmlSAXVersion (xmlSAXHandler *hdlr, int version); XMLPUBFUN void XMLCALL xmlSAX2InitDefaultSAXHandler (xmlSAXHandler *hdlr, int warning); #ifdef LIBXML_HTML_ENABLED XMLPUBFUN void XMLCALL xmlSAX2InitHtmlDefaultSAXHandler(xmlSAXHandler *hdlr); XMLPUBFUN void XMLCALL htmlDefaultSAXHandlerInit (void); #endif #ifdef LIBXML_DOCB_ENABLED XMLPUBFUN void XMLCALL xmlSAX2InitDocbDefaultSAXHandler(xmlSAXHandler *hdlr); XMLPUBFUN void XMLCALL docbDefaultSAXHandlerInit (void); #endif XMLPUBFUN void XMLCALL xmlDefaultSAXHandlerInit (void); #ifdef __cplusplus } #endif #endif /* __XML_SAX2_H__ */ PK!Llibxml/xmlschemas.hnu[/* * Summary: incomplete XML Schemas structure implementation * Description: interface to the XML Schemas handling and schema validity * checking, it is incomplete right now. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_SCHEMA_H__ #define __XML_SCHEMA_H__ #include #ifdef LIBXML_SCHEMAS_ENABLED #include #ifdef __cplusplus extern "C" { #endif /** * This error codes are obsolete; not used any more. */ typedef enum { XML_SCHEMAS_ERR_OK = 0, XML_SCHEMAS_ERR_NOROOT = 1, XML_SCHEMAS_ERR_UNDECLAREDELEM, XML_SCHEMAS_ERR_NOTTOPLEVEL, XML_SCHEMAS_ERR_MISSING, XML_SCHEMAS_ERR_WRONGELEM, XML_SCHEMAS_ERR_NOTYPE, XML_SCHEMAS_ERR_NOROLLBACK, XML_SCHEMAS_ERR_ISABSTRACT, XML_SCHEMAS_ERR_NOTEMPTY, XML_SCHEMAS_ERR_ELEMCONT, XML_SCHEMAS_ERR_HAVEDEFAULT, XML_SCHEMAS_ERR_NOTNILLABLE, XML_SCHEMAS_ERR_EXTRACONTENT, XML_SCHEMAS_ERR_INVALIDATTR, XML_SCHEMAS_ERR_INVALIDELEM, XML_SCHEMAS_ERR_NOTDETERMINIST, XML_SCHEMAS_ERR_CONSTRUCT, XML_SCHEMAS_ERR_INTERNAL, XML_SCHEMAS_ERR_NOTSIMPLE, XML_SCHEMAS_ERR_ATTRUNKNOWN, XML_SCHEMAS_ERR_ATTRINVALID, XML_SCHEMAS_ERR_VALUE, XML_SCHEMAS_ERR_FACET, XML_SCHEMAS_ERR_, XML_SCHEMAS_ERR_XXX } xmlSchemaValidError; /* * ATTENTION: Change xmlSchemaSetValidOptions's check * for invalid values, if adding to the validation * options below. */ /** * xmlSchemaValidOption: * * This is the set of XML Schema validation options. */ typedef enum { XML_SCHEMA_VAL_VC_I_CREATE = 1<<0 /* Default/fixed: create an attribute node * or an element's text node on the instance. */ } xmlSchemaValidOption; /* XML_SCHEMA_VAL_XSI_ASSEMBLE = 1<<1, * assemble schemata using * xsi:schemaLocation and * xsi:noNamespaceSchemaLocation */ /** * The schemas related types are kept internal */ typedef struct _xmlSchema xmlSchema; typedef xmlSchema *xmlSchemaPtr; /** * xmlSchemaValidityErrorFunc: * @ctx: the validation context * @msg: the message * @...: extra arguments * * Signature of an error callback from an XSD validation */ typedef void (XMLCDECL *xmlSchemaValidityErrorFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * xmlSchemaValidityWarningFunc: * @ctx: the validation context * @msg: the message * @...: extra arguments * * Signature of a warning callback from an XSD validation */ typedef void (XMLCDECL *xmlSchemaValidityWarningFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * A schemas validation context */ typedef struct _xmlSchemaParserCtxt xmlSchemaParserCtxt; typedef xmlSchemaParserCtxt *xmlSchemaParserCtxtPtr; typedef struct _xmlSchemaValidCtxt xmlSchemaValidCtxt; typedef xmlSchemaValidCtxt *xmlSchemaValidCtxtPtr; /** * xmlSchemaValidityLocatorFunc: * @ctx: user provided context * @file: returned file information * @line: returned line information * * A schemas validation locator, a callback called by the validator. * This is used when file or node information are not available * to find out what file and line number are affected * * Returns: 0 in case of success and -1 in case of error */ typedef int (XMLCDECL *xmlSchemaValidityLocatorFunc) (void *ctx, const char **file, unsigned long *line); /* * Interfaces for parsing. */ XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL xmlSchemaNewParserCtxt (const char *URL); XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL xmlSchemaNewMemParserCtxt (const char *buffer, int size); XMLPUBFUN xmlSchemaParserCtxtPtr XMLCALL xmlSchemaNewDocParserCtxt (xmlDocPtr doc); XMLPUBFUN void XMLCALL xmlSchemaFreeParserCtxt (xmlSchemaParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlSchemaSetParserErrors (xmlSchemaParserCtxtPtr ctxt, xmlSchemaValidityErrorFunc err, xmlSchemaValidityWarningFunc warn, void *ctx); XMLPUBFUN void XMLCALL xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt, xmlStructuredErrorFunc serror, void *ctx); XMLPUBFUN int XMLCALL xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt, xmlSchemaValidityErrorFunc * err, xmlSchemaValidityWarningFunc * warn, void **ctx); XMLPUBFUN int XMLCALL xmlSchemaIsValid (xmlSchemaValidCtxtPtr ctxt); XMLPUBFUN xmlSchemaPtr XMLCALL xmlSchemaParse (xmlSchemaParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlSchemaFree (xmlSchemaPtr schema); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlSchemaDump (FILE *output, xmlSchemaPtr schema); #endif /* LIBXML_OUTPUT_ENABLED */ /* * Interfaces for validating */ XMLPUBFUN void XMLCALL xmlSchemaSetValidErrors (xmlSchemaValidCtxtPtr ctxt, xmlSchemaValidityErrorFunc err, xmlSchemaValidityWarningFunc warn, void *ctx); XMLPUBFUN void XMLCALL xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt, xmlStructuredErrorFunc serror, void *ctx); XMLPUBFUN int XMLCALL xmlSchemaGetValidErrors (xmlSchemaValidCtxtPtr ctxt, xmlSchemaValidityErrorFunc *err, xmlSchemaValidityWarningFunc *warn, void **ctx); XMLPUBFUN int XMLCALL xmlSchemaSetValidOptions (xmlSchemaValidCtxtPtr ctxt, int options); XMLPUBFUN void XMLCALL xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename); XMLPUBFUN int XMLCALL xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt); XMLPUBFUN xmlSchemaValidCtxtPtr XMLCALL xmlSchemaNewValidCtxt (xmlSchemaPtr schema); XMLPUBFUN void XMLCALL xmlSchemaFreeValidCtxt (xmlSchemaValidCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlSchemaValidateDoc (xmlSchemaValidCtxtPtr ctxt, xmlDocPtr instance); XMLPUBFUN int XMLCALL xmlSchemaValidateOneElement (xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem); XMLPUBFUN int XMLCALL xmlSchemaValidateStream (xmlSchemaValidCtxtPtr ctxt, xmlParserInputBufferPtr input, xmlCharEncoding enc, xmlSAXHandlerPtr sax, void *user_data); XMLPUBFUN int XMLCALL xmlSchemaValidateFile (xmlSchemaValidCtxtPtr ctxt, const char * filename, int options); XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt); /* * Interface to insert Schemas SAX validation in a SAX stream */ typedef struct _xmlSchemaSAXPlug xmlSchemaSAXPlugStruct; typedef xmlSchemaSAXPlugStruct *xmlSchemaSAXPlugPtr; XMLPUBFUN xmlSchemaSAXPlugPtr XMLCALL xmlSchemaSAXPlug (xmlSchemaValidCtxtPtr ctxt, xmlSAXHandlerPtr *sax, void **user_data); XMLPUBFUN int XMLCALL xmlSchemaSAXUnplug (xmlSchemaSAXPlugPtr plug); XMLPUBFUN void XMLCALL xmlSchemaValidateSetLocator (xmlSchemaValidCtxtPtr vctxt, xmlSchemaValidityLocatorFunc f, void *ctxt); #ifdef __cplusplus } #endif #endif /* LIBXML_SCHEMAS_ENABLED */ #endif /* __XML_SCHEMA_H__ */ PK!Qulibxml/xmlmodule.hnu[/* * Summary: dynamic module loading * Description: basic API for dynamic module loading, used by * libexslt added in 2.6.17 * * Copy: See Copyright for the status of this software. * * Author: Joel W. Reed */ #ifndef __XML_MODULE_H__ #define __XML_MODULE_H__ #include #ifdef LIBXML_MODULES_ENABLED #ifdef __cplusplus extern "C" { #endif /** * xmlModulePtr: * * A handle to a dynamically loaded module */ typedef struct _xmlModule xmlModule; typedef xmlModule *xmlModulePtr; /** * xmlModuleOption: * * enumeration of options that can be passed down to xmlModuleOpen() */ typedef enum { XML_MODULE_LAZY = 1, /* lazy binding */ XML_MODULE_LOCAL= 2 /* local binding */ } xmlModuleOption; XMLPUBFUN xmlModulePtr XMLCALL xmlModuleOpen (const char *filename, int options); XMLPUBFUN int XMLCALL xmlModuleSymbol (xmlModulePtr module, const char* name, void **result); XMLPUBFUN int XMLCALL xmlModuleClose (xmlModulePtr module); XMLPUBFUN int XMLCALL xmlModuleFree (xmlModulePtr module); #ifdef __cplusplus } #endif #endif /* LIBXML_MODULES_ENABLED */ #endif /*__XML_MODULE_H__ */ PK!L! ! libxml/xmlsave.hnu[/* * Summary: the XML document serializer * Description: API to save document or subtree of document * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XMLSAVE_H__ #define __XML_XMLSAVE_H__ #include #include #include #include #ifdef LIBXML_OUTPUT_ENABLED #ifdef __cplusplus extern "C" { #endif /** * xmlSaveOption: * * This is the set of XML save options that can be passed down * to the xmlSaveToFd() and similar calls. */ typedef enum { XML_SAVE_FORMAT = 1<<0, /* format save output */ XML_SAVE_NO_DECL = 1<<1, /* drop the xml declaration */ XML_SAVE_NO_EMPTY = 1<<2, /* no empty tags */ XML_SAVE_NO_XHTML = 1<<3, /* disable XHTML1 specific rules */ XML_SAVE_XHTML = 1<<4, /* force XHTML1 specific rules */ XML_SAVE_AS_XML = 1<<5, /* force XML serialization on HTML doc */ XML_SAVE_AS_HTML = 1<<6, /* force HTML serialization on XML doc */ XML_SAVE_WSNONSIG = 1<<7 /* format with non-significant whitespace */ } xmlSaveOption; typedef struct _xmlSaveCtxt xmlSaveCtxt; typedef xmlSaveCtxt *xmlSaveCtxtPtr; XMLPUBFUN xmlSaveCtxtPtr XMLCALL xmlSaveToFd (int fd, const char *encoding, int options); XMLPUBFUN xmlSaveCtxtPtr XMLCALL xmlSaveToFilename (const char *filename, const char *encoding, int options); XMLPUBFUN xmlSaveCtxtPtr XMLCALL xmlSaveToBuffer (xmlBufferPtr buffer, const char *encoding, int options); XMLPUBFUN xmlSaveCtxtPtr XMLCALL xmlSaveToIO (xmlOutputWriteCallback iowrite, xmlOutputCloseCallback ioclose, void *ioctx, const char *encoding, int options); XMLPUBFUN long XMLCALL xmlSaveDoc (xmlSaveCtxtPtr ctxt, xmlDocPtr doc); XMLPUBFUN long XMLCALL xmlSaveTree (xmlSaveCtxtPtr ctxt, xmlNodePtr node); XMLPUBFUN int XMLCALL xmlSaveFlush (xmlSaveCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlSaveClose (xmlSaveCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlSaveSetEscape (xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape); XMLPUBFUN int XMLCALL xmlSaveSetAttrEscape (xmlSaveCtxtPtr ctxt, xmlCharEncodingOutputFunc escape); #ifdef __cplusplus } #endif #endif /* LIBXML_OUTPUT_ENABLED */ #endif /* __XML_XMLSAVE_H__ */ PK!HftKKlibxml/xpathInternals.hnu[/* * Summary: internal interfaces for XML Path Language implementation * Description: internal interfaces for XML Path Language implementation * used to build new modules on top of XPath like XPointer and * XSLT * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XPATH_INTERNALS_H__ #define __XML_XPATH_INTERNALS_H__ #include #include #ifdef LIBXML_XPATH_ENABLED #ifdef __cplusplus extern "C" { #endif /************************************************************************ * * * Helpers * * * ************************************************************************/ /* * Many of these macros may later turn into functions. They * shouldn't be used in #ifdef's preprocessor instructions. */ /** * xmlXPathSetError: * @ctxt: an XPath parser context * @err: an xmlXPathError code * * Raises an error. */ #define xmlXPathSetError(ctxt, err) \ { xmlXPatherror((ctxt), __FILE__, __LINE__, (err)); \ if ((ctxt) != NULL) (ctxt)->error = (err); } /** * xmlXPathSetArityError: * @ctxt: an XPath parser context * * Raises an XPATH_INVALID_ARITY error. */ #define xmlXPathSetArityError(ctxt) \ xmlXPathSetError((ctxt), XPATH_INVALID_ARITY) /** * xmlXPathSetTypeError: * @ctxt: an XPath parser context * * Raises an XPATH_INVALID_TYPE error. */ #define xmlXPathSetTypeError(ctxt) \ xmlXPathSetError((ctxt), XPATH_INVALID_TYPE) /** * xmlXPathGetError: * @ctxt: an XPath parser context * * Get the error code of an XPath context. * * Returns the context error. */ #define xmlXPathGetError(ctxt) ((ctxt)->error) /** * xmlXPathCheckError: * @ctxt: an XPath parser context * * Check if an XPath error was raised. * * Returns true if an error has been raised, false otherwise. */ #define xmlXPathCheckError(ctxt) ((ctxt)->error != XPATH_EXPRESSION_OK) /** * xmlXPathGetDocument: * @ctxt: an XPath parser context * * Get the document of an XPath context. * * Returns the context document. */ #define xmlXPathGetDocument(ctxt) ((ctxt)->context->doc) /** * xmlXPathGetContextNode: * @ctxt: an XPath parser context * * Get the context node of an XPath context. * * Returns the context node. */ #define xmlXPathGetContextNode(ctxt) ((ctxt)->context->node) XMLPUBFUN int XMLCALL xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt); XMLPUBFUN double XMLCALL xmlXPathPopNumber (xmlXPathParserContextPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlXPathPopString (xmlXPathParserContextPtr ctxt); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt); XMLPUBFUN void * XMLCALL xmlXPathPopExternal (xmlXPathParserContextPtr ctxt); /** * xmlXPathReturnBoolean: * @ctxt: an XPath parser context * @val: a boolean * * Pushes the boolean @val on the context stack. */ #define xmlXPathReturnBoolean(ctxt, val) \ valuePush((ctxt), xmlXPathNewBoolean(val)) /** * xmlXPathReturnTrue: * @ctxt: an XPath parser context * * Pushes true on the context stack. */ #define xmlXPathReturnTrue(ctxt) xmlXPathReturnBoolean((ctxt), 1) /** * xmlXPathReturnFalse: * @ctxt: an XPath parser context * * Pushes false on the context stack. */ #define xmlXPathReturnFalse(ctxt) xmlXPathReturnBoolean((ctxt), 0) /** * xmlXPathReturnNumber: * @ctxt: an XPath parser context * @val: a double * * Pushes the double @val on the context stack. */ #define xmlXPathReturnNumber(ctxt, val) \ valuePush((ctxt), xmlXPathNewFloat(val)) /** * xmlXPathReturnString: * @ctxt: an XPath parser context * @str: a string * * Pushes the string @str on the context stack. */ #define xmlXPathReturnString(ctxt, str) \ valuePush((ctxt), xmlXPathWrapString(str)) /** * xmlXPathReturnEmptyString: * @ctxt: an XPath parser context * * Pushes an empty string on the stack. */ #define xmlXPathReturnEmptyString(ctxt) \ valuePush((ctxt), xmlXPathNewCString("")) /** * xmlXPathReturnNodeSet: * @ctxt: an XPath parser context * @ns: a node-set * * Pushes the node-set @ns on the context stack. */ #define xmlXPathReturnNodeSet(ctxt, ns) \ valuePush((ctxt), xmlXPathWrapNodeSet(ns)) /** * xmlXPathReturnEmptyNodeSet: * @ctxt: an XPath parser context * * Pushes an empty node-set on the context stack. */ #define xmlXPathReturnEmptyNodeSet(ctxt) \ valuePush((ctxt), xmlXPathNewNodeSet(NULL)) /** * xmlXPathReturnExternal: * @ctxt: an XPath parser context * @val: user data * * Pushes user data on the context stack. */ #define xmlXPathReturnExternal(ctxt, val) \ valuePush((ctxt), xmlXPathWrapExternal(val)) /** * xmlXPathStackIsNodeSet: * @ctxt: an XPath parser context * * Check if the current value on the XPath stack is a node set or * an XSLT value tree. * * Returns true if the current object on the stack is a node-set. */ #define xmlXPathStackIsNodeSet(ctxt) \ (((ctxt)->value != NULL) \ && (((ctxt)->value->type == XPATH_NODESET) \ || ((ctxt)->value->type == XPATH_XSLT_TREE))) /** * xmlXPathStackIsExternal: * @ctxt: an XPath parser context * * Checks if the current value on the XPath stack is an external * object. * * Returns true if the current object on the stack is an external * object. */ #define xmlXPathStackIsExternal(ctxt) \ ((ctxt->value != NULL) && (ctxt->value->type == XPATH_USERS)) /** * xmlXPathEmptyNodeSet: * @ns: a node-set * * Empties a node-set. */ #define xmlXPathEmptyNodeSet(ns) \ { while ((ns)->nodeNr > 0) (ns)->nodeTab[--(ns)->nodeNr] = NULL; } /** * CHECK_ERROR: * * Macro to return from the function if an XPath error was detected. */ #define CHECK_ERROR \ if (ctxt->error != XPATH_EXPRESSION_OK) return /** * CHECK_ERROR0: * * Macro to return 0 from the function if an XPath error was detected. */ #define CHECK_ERROR0 \ if (ctxt->error != XPATH_EXPRESSION_OK) return(0) /** * XP_ERROR: * @X: the error code * * Macro to raise an XPath error and return. */ #define XP_ERROR(X) \ { xmlXPathErr(ctxt, X); return; } /** * XP_ERROR0: * @X: the error code * * Macro to raise an XPath error and return 0. */ #define XP_ERROR0(X) \ { xmlXPathErr(ctxt, X); return(0); } /** * CHECK_TYPE: * @typeval: the XPath type * * Macro to check that the value on top of the XPath stack is of a given * type. */ #define CHECK_TYPE(typeval) \ if ((ctxt->value == NULL) || (ctxt->value->type != typeval)) \ XP_ERROR(XPATH_INVALID_TYPE) /** * CHECK_TYPE0: * @typeval: the XPath type * * Macro to check that the value on top of the XPath stack is of a given * type. Return(0) in case of failure */ #define CHECK_TYPE0(typeval) \ if ((ctxt->value == NULL) || (ctxt->value->type != typeval)) \ XP_ERROR0(XPATH_INVALID_TYPE) /** * CHECK_ARITY: * @x: the number of expected args * * Macro to check that the number of args passed to an XPath function matches. */ #define CHECK_ARITY(x) \ if (ctxt == NULL) return; \ if (nargs != (x)) \ XP_ERROR(XPATH_INVALID_ARITY); \ if (ctxt->valueNr < ctxt->valueFrame + (x)) \ XP_ERROR(XPATH_STACK_ERROR); /** * CAST_TO_STRING: * * Macro to try to cast the value on the top of the XPath stack to a string. */ #define CAST_TO_STRING \ if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_STRING)) \ xmlXPathStringFunction(ctxt, 1); /** * CAST_TO_NUMBER: * * Macro to try to cast the value on the top of the XPath stack to a number. */ #define CAST_TO_NUMBER \ if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_NUMBER)) \ xmlXPathNumberFunction(ctxt, 1); /** * CAST_TO_BOOLEAN: * * Macro to try to cast the value on the top of the XPath stack to a boolean. */ #define CAST_TO_BOOLEAN \ if ((ctxt->value != NULL) && (ctxt->value->type != XPATH_BOOLEAN)) \ xmlXPathBooleanFunction(ctxt, 1); /* * Variable Lookup forwarding. */ XMLPUBFUN void XMLCALL xmlXPathRegisterVariableLookup (xmlXPathContextPtr ctxt, xmlXPathVariableLookupFunc f, void *data); /* * Function Lookup forwarding. */ XMLPUBFUN void XMLCALL xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt, xmlXPathFuncLookupFunc f, void *funcCtxt); /* * Error reporting. */ XMLPUBFUN void XMLCALL xmlXPatherror (xmlXPathParserContextPtr ctxt, const char *file, int line, int no); XMLPUBFUN void XMLCALL xmlXPathErr (xmlXPathParserContextPtr ctxt, int error); #ifdef LIBXML_DEBUG_ENABLED XMLPUBFUN void XMLCALL xmlXPathDebugDumpObject (FILE *output, xmlXPathObjectPtr cur, int depth); XMLPUBFUN void XMLCALL xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp, int depth); #endif /** * NodeSet handling. */ XMLPUBFUN int XMLCALL xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathDistinctSorted (xmlNodeSetPtr nodes); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathDistinct (xmlNodeSetPtr nodes); XMLPUBFUN int XMLCALL xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2); /** * Extending a context. */ XMLPUBFUN int XMLCALL xmlXPathRegisterNs (xmlXPathContextPtr ctxt, const xmlChar *prefix, const xmlChar *ns_uri); XMLPUBFUN const xmlChar * XMLCALL xmlXPathNsLookup (xmlXPathContextPtr ctxt, const xmlChar *prefix); XMLPUBFUN void XMLCALL xmlXPathRegisteredNsCleanup (xmlXPathContextPtr ctxt); XMLPUBFUN int XMLCALL xmlXPathRegisterFunc (xmlXPathContextPtr ctxt, const xmlChar *name, xmlXPathFunction f); XMLPUBFUN int XMLCALL xmlXPathRegisterFuncNS (xmlXPathContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri, xmlXPathFunction f); XMLPUBFUN int XMLCALL xmlXPathRegisterVariable (xmlXPathContextPtr ctxt, const xmlChar *name, xmlXPathObjectPtr value); XMLPUBFUN int XMLCALL xmlXPathRegisterVariableNS (xmlXPathContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri, xmlXPathObjectPtr value); XMLPUBFUN xmlXPathFunction XMLCALL xmlXPathFunctionLookup (xmlXPathContextPtr ctxt, const xmlChar *name); XMLPUBFUN xmlXPathFunction XMLCALL xmlXPathFunctionLookupNS (xmlXPathContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri); XMLPUBFUN void XMLCALL xmlXPathRegisteredFuncsCleanup (xmlXPathContextPtr ctxt); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathVariableLookup (xmlXPathContextPtr ctxt, const xmlChar *name); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathVariableLookupNS (xmlXPathContextPtr ctxt, const xmlChar *name, const xmlChar *ns_uri); XMLPUBFUN void XMLCALL xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt); /** * Utilities to extend XPath. */ XMLPUBFUN xmlXPathParserContextPtr XMLCALL xmlXPathNewParserContext (const xmlChar *str, xmlXPathContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathFreeParserContext (xmlXPathParserContextPtr ctxt); /* TODO: remap to xmlXPathValuePop and Push. */ XMLPUBFUN xmlXPathObjectPtr XMLCALL valuePop (xmlXPathParserContextPtr ctxt); XMLPUBFUN int XMLCALL valuePush (xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNewString (const xmlChar *val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNewCString (const char *val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathWrapString (xmlChar *val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathWrapCString (char * val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNewFloat (double val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNewBoolean (int val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNewNodeSet (xmlNodePtr val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNewValueTree (xmlNodePtr val); XMLPUBFUN int XMLCALL xmlXPathNodeSetAdd (xmlNodeSetPtr cur, xmlNodePtr val); XMLPUBFUN int XMLCALL xmlXPathNodeSetAddUnique (xmlNodeSetPtr cur, xmlNodePtr val); XMLPUBFUN int XMLCALL xmlXPathNodeSetAddNs (xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns); XMLPUBFUN void XMLCALL xmlXPathNodeSetSort (xmlNodeSetPtr set); XMLPUBFUN void XMLCALL xmlXPathRoot (xmlXPathParserContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathEvalExpr (xmlXPathParserContextPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlXPathParseName (xmlXPathParserContextPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlXPathParseNCName (xmlXPathParserContextPtr ctxt); /* * Existing functions. */ XMLPUBFUN double XMLCALL xmlXPathStringEvalNumber (const xmlChar *str); XMLPUBFUN int XMLCALL xmlXPathEvaluatePredicateResult (xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr res); XMLPUBFUN void XMLCALL xmlXPathRegisterAllFunctions (xmlXPathContextPtr ctxt); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathNodeSetMerge (xmlNodeSetPtr val1, xmlNodeSetPtr val2); XMLPUBFUN void XMLCALL xmlXPathNodeSetDel (xmlNodeSetPtr cur, xmlNodePtr val); XMLPUBFUN void XMLCALL xmlXPathNodeSetRemove (xmlNodeSetPtr cur, int val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNewNodeSetList (xmlNodeSetPtr val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathWrapNodeSet (xmlNodeSetPtr val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathWrapExternal (void *val); XMLPUBFUN int XMLCALL xmlXPathEqualValues(xmlXPathParserContextPtr ctxt); XMLPUBFUN int XMLCALL xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt); XMLPUBFUN int XMLCALL xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict); XMLPUBFUN void XMLCALL xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathAddValues(xmlXPathParserContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathSubValues(xmlXPathParserContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathMultValues(xmlXPathParserContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathDivValues(xmlXPathParserContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathModValues(xmlXPathParserContextPtr ctxt); XMLPUBFUN int XMLCALL xmlXPathIsNodeType(const xmlChar *name); /* * Some of the axis navigation routines. */ XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); XMLPUBFUN xmlNodePtr XMLCALL xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur); /* * The official core of XPath functions. */ XMLPUBFUN void XMLCALL xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN void XMLCALL xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs); /** * Really internal functions */ XMLPUBFUN void XMLCALL xmlXPathNodeSetFreeNs(xmlNsPtr ns); #ifdef __cplusplus } #endif #endif /* LIBXML_XPATH_ENABLED */ #endif /* ! __XML_XPATH_INTERNALS_H__ */ PK!*Lh h libxml/uri.hnu[/** * Summary: library of generic URI related routines * Description: library of generic URI related routines * Implements RFC 2396 * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_URI_H__ #define __XML_URI_H__ #include #include #ifdef __cplusplus extern "C" { #endif /** * xmlURI: * * A parsed URI reference. This is a struct containing the various fields * as described in RFC 2396 but separated for further processing. * * Note: query is a deprecated field which is incorrectly unescaped. * query_raw takes precedence over query if the former is set. * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00127 */ typedef struct _xmlURI xmlURI; typedef xmlURI *xmlURIPtr; struct _xmlURI { char *scheme; /* the URI scheme */ char *opaque; /* opaque part */ char *authority; /* the authority part */ char *server; /* the server part */ char *user; /* the user part */ int port; /* the port number */ char *path; /* the path string */ char *query; /* the query string (deprecated - use with caution) */ char *fragment; /* the fragment identifier */ int cleanup; /* parsing potentially unclean URI */ char *query_raw; /* the query string (as it appears in the URI) */ }; /* * This function is in tree.h: * xmlChar * xmlNodeGetBase (xmlDocPtr doc, * xmlNodePtr cur); */ XMLPUBFUN xmlURIPtr XMLCALL xmlCreateURI (void); XMLPUBFUN xmlChar * XMLCALL xmlBuildURI (const xmlChar *URI, const xmlChar *base); XMLPUBFUN xmlChar * XMLCALL xmlBuildRelativeURI (const xmlChar *URI, const xmlChar *base); XMLPUBFUN xmlURIPtr XMLCALL xmlParseURI (const char *str); XMLPUBFUN xmlURIPtr XMLCALL xmlParseURIRaw (const char *str, int raw); XMLPUBFUN int XMLCALL xmlParseURIReference (xmlURIPtr uri, const char *str); XMLPUBFUN xmlChar * XMLCALL xmlSaveUri (xmlURIPtr uri); XMLPUBFUN void XMLCALL xmlPrintURI (FILE *stream, xmlURIPtr uri); XMLPUBFUN xmlChar * XMLCALL xmlURIEscapeStr (const xmlChar *str, const xmlChar *list); XMLPUBFUN char * XMLCALL xmlURIUnescapeString (const char *str, int len, char *target); XMLPUBFUN int XMLCALL xmlNormalizeURIPath (char *path); XMLPUBFUN xmlChar * XMLCALL xmlURIEscape (const xmlChar *str); XMLPUBFUN void XMLCALL xmlFreeURI (xmlURIPtr uri); XMLPUBFUN xmlChar* XMLCALL xmlCanonicPath (const xmlChar *path); XMLPUBFUN xmlChar* XMLCALL xmlPathToURI (const xmlChar *path); #ifdef __cplusplus } #endif #endif /* __XML_URI_H__ */ PK!ԺLlibxml/xmlschemastypes.hnu[/* * Summary: implementation of XML Schema Datatypes * Description: module providing the XML Schema Datatypes implementation * both definition and validity checking * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_SCHEMA_TYPES_H__ #define __XML_SCHEMA_TYPES_H__ #include #ifdef LIBXML_SCHEMAS_ENABLED #include #include #ifdef __cplusplus extern "C" { #endif typedef enum { XML_SCHEMA_WHITESPACE_UNKNOWN = 0, XML_SCHEMA_WHITESPACE_PRESERVE = 1, XML_SCHEMA_WHITESPACE_REPLACE = 2, XML_SCHEMA_WHITESPACE_COLLAPSE = 3 } xmlSchemaWhitespaceValueType; XMLPUBFUN void XMLCALL xmlSchemaInitTypes (void); XMLPUBFUN void XMLCALL xmlSchemaCleanupTypes (void); XMLPUBFUN xmlSchemaTypePtr XMLCALL xmlSchemaGetPredefinedType (const xmlChar *name, const xmlChar *ns); XMLPUBFUN int XMLCALL xmlSchemaValidatePredefinedType (xmlSchemaTypePtr type, const xmlChar *value, xmlSchemaValPtr *val); XMLPUBFUN int XMLCALL xmlSchemaValPredefTypeNode (xmlSchemaTypePtr type, const xmlChar *value, xmlSchemaValPtr *val, xmlNodePtr node); XMLPUBFUN int XMLCALL xmlSchemaValidateFacet (xmlSchemaTypePtr base, xmlSchemaFacetPtr facet, const xmlChar *value, xmlSchemaValPtr val); XMLPUBFUN int XMLCALL xmlSchemaValidateFacetWhtsp (xmlSchemaFacetPtr facet, xmlSchemaWhitespaceValueType fws, xmlSchemaValType valType, const xmlChar *value, xmlSchemaValPtr val, xmlSchemaWhitespaceValueType ws); XMLPUBFUN void XMLCALL xmlSchemaFreeValue (xmlSchemaValPtr val); XMLPUBFUN xmlSchemaFacetPtr XMLCALL xmlSchemaNewFacet (void); XMLPUBFUN int XMLCALL xmlSchemaCheckFacet (xmlSchemaFacetPtr facet, xmlSchemaTypePtr typeDecl, xmlSchemaParserCtxtPtr ctxt, const xmlChar *name); XMLPUBFUN void XMLCALL xmlSchemaFreeFacet (xmlSchemaFacetPtr facet); XMLPUBFUN int XMLCALL xmlSchemaCompareValues (xmlSchemaValPtr x, xmlSchemaValPtr y); XMLPUBFUN xmlSchemaTypePtr XMLCALL xmlSchemaGetBuiltInListSimpleTypeItemType (xmlSchemaTypePtr type); XMLPUBFUN int XMLCALL xmlSchemaValidateListSimpleTypeFacet (xmlSchemaFacetPtr facet, const xmlChar *value, unsigned long actualLen, unsigned long *expectedLen); XMLPUBFUN xmlSchemaTypePtr XMLCALL xmlSchemaGetBuiltInType (xmlSchemaValType type); XMLPUBFUN int XMLCALL xmlSchemaIsBuiltInTypeFacet (xmlSchemaTypePtr type, int facetType); XMLPUBFUN xmlChar * XMLCALL xmlSchemaCollapseString (const xmlChar *value); XMLPUBFUN xmlChar * XMLCALL xmlSchemaWhiteSpaceReplace (const xmlChar *value); XMLPUBFUN unsigned long XMLCALL xmlSchemaGetFacetValueAsULong (xmlSchemaFacetPtr facet); XMLPUBFUN int XMLCALL xmlSchemaValidateLengthFacet (xmlSchemaTypePtr type, xmlSchemaFacetPtr facet, const xmlChar *value, xmlSchemaValPtr val, unsigned long *length); XMLPUBFUN int XMLCALL xmlSchemaValidateLengthFacetWhtsp(xmlSchemaFacetPtr facet, xmlSchemaValType valType, const xmlChar *value, xmlSchemaValPtr val, unsigned long *length, xmlSchemaWhitespaceValueType ws); XMLPUBFUN int XMLCALL xmlSchemaValPredefTypeNodeNoNorm(xmlSchemaTypePtr type, const xmlChar *value, xmlSchemaValPtr *val, xmlNodePtr node); XMLPUBFUN int XMLCALL xmlSchemaGetCanonValue (xmlSchemaValPtr val, const xmlChar **retValue); XMLPUBFUN int XMLCALL xmlSchemaGetCanonValueWhtsp (xmlSchemaValPtr val, const xmlChar **retValue, xmlSchemaWhitespaceValueType ws); XMLPUBFUN int XMLCALL xmlSchemaValueAppend (xmlSchemaValPtr prev, xmlSchemaValPtr cur); XMLPUBFUN xmlSchemaValPtr XMLCALL xmlSchemaValueGetNext (xmlSchemaValPtr cur); XMLPUBFUN const xmlChar * XMLCALL xmlSchemaValueGetAsString (xmlSchemaValPtr val); XMLPUBFUN int XMLCALL xmlSchemaValueGetAsBoolean (xmlSchemaValPtr val); XMLPUBFUN xmlSchemaValPtr XMLCALL xmlSchemaNewStringValue (xmlSchemaValType type, const xmlChar *value); XMLPUBFUN xmlSchemaValPtr XMLCALL xmlSchemaNewNOTATIONValue (const xmlChar *name, const xmlChar *ns); XMLPUBFUN xmlSchemaValPtr XMLCALL xmlSchemaNewQNameValue (const xmlChar *namespaceName, const xmlChar *localName); XMLPUBFUN int XMLCALL xmlSchemaCompareValuesWhtsp (xmlSchemaValPtr x, xmlSchemaWhitespaceValueType xws, xmlSchemaValPtr y, xmlSchemaWhitespaceValueType yws); XMLPUBFUN xmlSchemaValPtr XMLCALL xmlSchemaCopyValue (xmlSchemaValPtr val); XMLPUBFUN xmlSchemaValType XMLCALL xmlSchemaGetValType (xmlSchemaValPtr val); #ifdef __cplusplus } #endif #endif /* LIBXML_SCHEMAS_ENABLED */ #endif /* __XML_SCHEMA_TYPES_H__ */ PK!c+libxml/__pycache__/__init__.cpython-311.pycnu[ idS)Nr/builddir/build/BUILD/imunify360-venv-2.6.2/opt/imunify360/venv/lib64/python3.11/site-packages/lxml/includes/libxml/__init__.pyrsrPK!libxml/schematron.hnu[/* * Summary: XML Schemastron implementation * Description: interface to the XML Schematron validity checking. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_SCHEMATRON_H__ #define __XML_SCHEMATRON_H__ #include #ifdef LIBXML_SCHEMATRON_ENABLED #include #ifdef __cplusplus extern "C" { #endif typedef enum { XML_SCHEMATRON_OUT_QUIET = 1 << 0, /* quiet no report */ XML_SCHEMATRON_OUT_TEXT = 1 << 1, /* build a textual report */ XML_SCHEMATRON_OUT_XML = 1 << 2, /* output SVRL */ XML_SCHEMATRON_OUT_ERROR = 1 << 3, /* output via xmlStructuredErrorFunc */ XML_SCHEMATRON_OUT_FILE = 1 << 8, /* output to a file descriptor */ XML_SCHEMATRON_OUT_BUFFER = 1 << 9, /* output to a buffer */ XML_SCHEMATRON_OUT_IO = 1 << 10 /* output to I/O mechanism */ } xmlSchematronValidOptions; /** * The schemas related types are kept internal */ typedef struct _xmlSchematron xmlSchematron; typedef xmlSchematron *xmlSchematronPtr; /** * xmlSchematronValidityErrorFunc: * @ctx: the validation context * @msg: the message * @...: extra arguments * * Signature of an error callback from a Schematron validation */ typedef void (*xmlSchematronValidityErrorFunc) (void *ctx, const char *msg, ...); /** * xmlSchematronValidityWarningFunc: * @ctx: the validation context * @msg: the message * @...: extra arguments * * Signature of a warning callback from a Schematron validation */ typedef void (*xmlSchematronValidityWarningFunc) (void *ctx, const char *msg, ...); /** * A schemas validation context */ typedef struct _xmlSchematronParserCtxt xmlSchematronParserCtxt; typedef xmlSchematronParserCtxt *xmlSchematronParserCtxtPtr; typedef struct _xmlSchematronValidCtxt xmlSchematronValidCtxt; typedef xmlSchematronValidCtxt *xmlSchematronValidCtxtPtr; /* * Interfaces for parsing. */ XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL xmlSchematronNewParserCtxt (const char *URL); XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL xmlSchematronNewMemParserCtxt(const char *buffer, int size); XMLPUBFUN xmlSchematronParserCtxtPtr XMLCALL xmlSchematronNewDocParserCtxt(xmlDocPtr doc); XMLPUBFUN void XMLCALL xmlSchematronFreeParserCtxt (xmlSchematronParserCtxtPtr ctxt); /***** XMLPUBFUN void XMLCALL xmlSchematronSetParserErrors(xmlSchematronParserCtxtPtr ctxt, xmlSchematronValidityErrorFunc err, xmlSchematronValidityWarningFunc warn, void *ctx); XMLPUBFUN int XMLCALL xmlSchematronGetParserErrors(xmlSchematronParserCtxtPtr ctxt, xmlSchematronValidityErrorFunc * err, xmlSchematronValidityWarningFunc * warn, void **ctx); XMLPUBFUN int XMLCALL xmlSchematronIsValid (xmlSchematronValidCtxtPtr ctxt); *****/ XMLPUBFUN xmlSchematronPtr XMLCALL xmlSchematronParse (xmlSchematronParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlSchematronFree (xmlSchematronPtr schema); /* * Interfaces for validating */ XMLPUBFUN void XMLCALL xmlSchematronSetValidStructuredErrors( xmlSchematronValidCtxtPtr ctxt, xmlStructuredErrorFunc serror, void *ctx); /****** XMLPUBFUN void XMLCALL xmlSchematronSetValidErrors (xmlSchematronValidCtxtPtr ctxt, xmlSchematronValidityErrorFunc err, xmlSchematronValidityWarningFunc warn, void *ctx); XMLPUBFUN int XMLCALL xmlSchematronGetValidErrors (xmlSchematronValidCtxtPtr ctxt, xmlSchematronValidityErrorFunc *err, xmlSchematronValidityWarningFunc *warn, void **ctx); XMLPUBFUN int XMLCALL xmlSchematronSetValidOptions(xmlSchematronValidCtxtPtr ctxt, int options); XMLPUBFUN int XMLCALL xmlSchematronValidCtxtGetOptions(xmlSchematronValidCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlSchematronValidateOneElement (xmlSchematronValidCtxtPtr ctxt, xmlNodePtr elem); *******/ XMLPUBFUN xmlSchematronValidCtxtPtr XMLCALL xmlSchematronNewValidCtxt (xmlSchematronPtr schema, int options); XMLPUBFUN void XMLCALL xmlSchematronFreeValidCtxt (xmlSchematronValidCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlSchematronValidateDoc (xmlSchematronValidCtxtPtr ctxt, xmlDocPtr instance); #ifdef __cplusplus } #endif #endif /* LIBXML_SCHEMATRON_ENABLED */ #endif /* __XML_SCHEMATRON_H__ */ PK!f?ttlibxml/xmlautomata.hnu[/* * Summary: API to build regexp automata * Description: the API to build regexp automata * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_AUTOMATA_H__ #define __XML_AUTOMATA_H__ #include #include #ifdef LIBXML_REGEXP_ENABLED #ifdef LIBXML_AUTOMATA_ENABLED #include #ifdef __cplusplus extern "C" { #endif /** * xmlAutomataPtr: * * A libxml automata description, It can be compiled into a regexp */ typedef struct _xmlAutomata xmlAutomata; typedef xmlAutomata *xmlAutomataPtr; /** * xmlAutomataStatePtr: * * A state int the automata description, */ typedef struct _xmlAutomataState xmlAutomataState; typedef xmlAutomataState *xmlAutomataStatePtr; /* * Building API */ XMLPUBFUN xmlAutomataPtr XMLCALL xmlNewAutomata (void); XMLPUBFUN void XMLCALL xmlFreeAutomata (xmlAutomataPtr am); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataGetInitState (xmlAutomataPtr am); XMLPUBFUN int XMLCALL xmlAutomataSetFinalState (xmlAutomataPtr am, xmlAutomataStatePtr state); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewState (xmlAutomataPtr am); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewTransition (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, const xmlChar *token, void *data); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewTransition2 (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, const xmlChar *token, const xmlChar *token2, void *data); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewNegTrans (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, const xmlChar *token, const xmlChar *token2, void *data); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewCountTrans (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, const xmlChar *token, int min, int max, void *data); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewCountTrans2 (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, const xmlChar *token, const xmlChar *token2, int min, int max, void *data); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewOnceTrans (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, const xmlChar *token, int min, int max, void *data); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewOnceTrans2 (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, const xmlChar *token, const xmlChar *token2, int min, int max, void *data); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewAllTrans (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, int lax); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewEpsilon (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewCountedTrans (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, int counter); XMLPUBFUN xmlAutomataStatePtr XMLCALL xmlAutomataNewCounterTrans (xmlAutomataPtr am, xmlAutomataStatePtr from, xmlAutomataStatePtr to, int counter); XMLPUBFUN int XMLCALL xmlAutomataNewCounter (xmlAutomataPtr am, int min, int max); XMLPUBFUN xmlRegexpPtr XMLCALL xmlAutomataCompile (xmlAutomataPtr am); XMLPUBFUN int XMLCALL xmlAutomataIsDeterminist (xmlAutomataPtr am); #ifdef __cplusplus } #endif #endif /* LIBXML_AUTOMATA_ENABLED */ #endif /* LIBXML_REGEXP_ENABLED */ #endif /* __XML_AUTOMATA_H__ */ PK!mI}T;!;!libxml/encoding.hnu[/* * Summary: interface for the encoding conversion functions * Description: interface for the encoding conversion functions needed for * XML basic encoding and iconv() support. * * Related specs are * rfc2044 (UTF-8 and UTF-16) F. Yergeau Alis Technologies * [ISO-10646] UTF-8 and UTF-16 in Annexes * [ISO-8859-1] ISO Latin-1 characters codes. * [UNICODE] The Unicode Consortium, "The Unicode Standard -- * Worldwide Character Encoding -- Version 1.0", Addison- * Wesley, Volume 1, 1991, Volume 2, 1992. UTF-8 is * described in Unicode Technical Report #4. * [US-ASCII] Coded Character Set--7-bit American Standard Code for * Information Interchange, ANSI X3.4-1986. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_CHAR_ENCODING_H__ #define __XML_CHAR_ENCODING_H__ #include #ifdef LIBXML_ICONV_ENABLED #include #endif #ifdef LIBXML_ICU_ENABLED #include #endif #ifdef __cplusplus extern "C" { #endif /* * xmlCharEncoding: * * Predefined values for some standard encodings. * Libxml does not do beforehand translation on UTF8 and ISOLatinX. * It also supports ASCII, ISO-8859-1, and UTF16 (LE and BE) by default. * * Anything else would have to be translated to UTF8 before being * given to the parser itself. The BOM for UTF16 and the encoding * declaration are looked at and a converter is looked for at that * point. If not found the parser stops here as asked by the XML REC. A * converter can be registered by the user using xmlRegisterCharEncodingHandler * but the current form doesn't allow stateful transcoding (a serious * problem agreed !). If iconv has been found it will be used * automatically and allow stateful transcoding, the simplest is then * to be sure to enable iconv and to provide iconv libs for the encoding * support needed. * * Note that the generic "UTF-16" is not a predefined value. Instead, only * the specific UTF-16LE and UTF-16BE are present. */ typedef enum { XML_CHAR_ENCODING_ERROR= -1, /* No char encoding detected */ XML_CHAR_ENCODING_NONE= 0, /* No char encoding detected */ XML_CHAR_ENCODING_UTF8= 1, /* UTF-8 */ XML_CHAR_ENCODING_UTF16LE= 2, /* UTF-16 little endian */ XML_CHAR_ENCODING_UTF16BE= 3, /* UTF-16 big endian */ XML_CHAR_ENCODING_UCS4LE= 4, /* UCS-4 little endian */ XML_CHAR_ENCODING_UCS4BE= 5, /* UCS-4 big endian */ XML_CHAR_ENCODING_EBCDIC= 6, /* EBCDIC uh! */ XML_CHAR_ENCODING_UCS4_2143=7, /* UCS-4 unusual ordering */ XML_CHAR_ENCODING_UCS4_3412=8, /* UCS-4 unusual ordering */ XML_CHAR_ENCODING_UCS2= 9, /* UCS-2 */ XML_CHAR_ENCODING_8859_1= 10,/* ISO-8859-1 ISO Latin 1 */ XML_CHAR_ENCODING_8859_2= 11,/* ISO-8859-2 ISO Latin 2 */ XML_CHAR_ENCODING_8859_3= 12,/* ISO-8859-3 */ XML_CHAR_ENCODING_8859_4= 13,/* ISO-8859-4 */ XML_CHAR_ENCODING_8859_5= 14,/* ISO-8859-5 */ XML_CHAR_ENCODING_8859_6= 15,/* ISO-8859-6 */ XML_CHAR_ENCODING_8859_7= 16,/* ISO-8859-7 */ XML_CHAR_ENCODING_8859_8= 17,/* ISO-8859-8 */ XML_CHAR_ENCODING_8859_9= 18,/* ISO-8859-9 */ XML_CHAR_ENCODING_2022_JP= 19,/* ISO-2022-JP */ XML_CHAR_ENCODING_SHIFT_JIS=20,/* Shift_JIS */ XML_CHAR_ENCODING_EUC_JP= 21,/* EUC-JP */ XML_CHAR_ENCODING_ASCII= 22 /* pure ASCII */ } xmlCharEncoding; /** * xmlCharEncodingInputFunc: * @out: a pointer to an array of bytes to store the UTF-8 result * @outlen: the length of @out * @in: a pointer to an array of chars in the original encoding * @inlen: the length of @in * * Take a block of chars in the original encoding and try to convert * it to an UTF-8 block of chars out. * * Returns the number of bytes written, -1 if lack of space, or -2 * if the transcoding failed. * The value of @inlen after return is the number of octets consumed * if the return value is positive, else unpredictiable. * The value of @outlen after return is the number of octets consumed. */ typedef int (* xmlCharEncodingInputFunc)(unsigned char *out, int *outlen, const unsigned char *in, int *inlen); /** * xmlCharEncodingOutputFunc: * @out: a pointer to an array of bytes to store the result * @outlen: the length of @out * @in: a pointer to an array of UTF-8 chars * @inlen: the length of @in * * Take a block of UTF-8 chars in and try to convert it to another * encoding. * Note: a first call designed to produce heading info is called with * in = NULL. If stateful this should also initialize the encoder state. * * Returns the number of bytes written, -1 if lack of space, or -2 * if the transcoding failed. * The value of @inlen after return is the number of octets consumed * if the return value is positive, else unpredictiable. * The value of @outlen after return is the number of octets produced. */ typedef int (* xmlCharEncodingOutputFunc)(unsigned char *out, int *outlen, const unsigned char *in, int *inlen); /* * Block defining the handlers for non UTF-8 encodings. * If iconv is supported, there are two extra fields. */ #ifdef LIBXML_ICU_ENABLED /* Size of pivot buffer, same as icu/source/common/ucnv.cpp CHUNK_SIZE */ #define ICU_PIVOT_BUF_SIZE 1024 struct _uconv_t { UConverter *uconv; /* for conversion between an encoding and UTF-16 */ UConverter *utf8; /* for conversion between UTF-8 and UTF-16 */ UChar pivot_buf[ICU_PIVOT_BUF_SIZE]; UChar *pivot_source; UChar *pivot_target; }; typedef struct _uconv_t uconv_t; #endif typedef struct _xmlCharEncodingHandler xmlCharEncodingHandler; typedef xmlCharEncodingHandler *xmlCharEncodingHandlerPtr; struct _xmlCharEncodingHandler { char *name; xmlCharEncodingInputFunc input; xmlCharEncodingOutputFunc output; #ifdef LIBXML_ICONV_ENABLED iconv_t iconv_in; iconv_t iconv_out; #endif /* LIBXML_ICONV_ENABLED */ #ifdef LIBXML_ICU_ENABLED uconv_t *uconv_in; uconv_t *uconv_out; #endif /* LIBXML_ICU_ENABLED */ }; #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif /* * Interfaces for encoding handlers. */ XMLPUBFUN void XMLCALL xmlInitCharEncodingHandlers (void); XMLPUBFUN void XMLCALL xmlCleanupCharEncodingHandlers (void); XMLPUBFUN void XMLCALL xmlRegisterCharEncodingHandler (xmlCharEncodingHandlerPtr handler); XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlGetCharEncodingHandler (xmlCharEncoding enc); XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlFindCharEncodingHandler (const char *name); XMLPUBFUN xmlCharEncodingHandlerPtr XMLCALL xmlNewCharEncodingHandler (const char *name, xmlCharEncodingInputFunc input, xmlCharEncodingOutputFunc output); /* * Interfaces for encoding names and aliases. */ XMLPUBFUN int XMLCALL xmlAddEncodingAlias (const char *name, const char *alias); XMLPUBFUN int XMLCALL xmlDelEncodingAlias (const char *alias); XMLPUBFUN const char * XMLCALL xmlGetEncodingAlias (const char *alias); XMLPUBFUN void XMLCALL xmlCleanupEncodingAliases (void); XMLPUBFUN xmlCharEncoding XMLCALL xmlParseCharEncoding (const char *name); XMLPUBFUN const char * XMLCALL xmlGetCharEncodingName (xmlCharEncoding enc); /* * Interfaces directly used by the parsers. */ XMLPUBFUN xmlCharEncoding XMLCALL xmlDetectCharEncoding (const unsigned char *in, int len); XMLPUBFUN int XMLCALL xmlCharEncOutFunc (xmlCharEncodingHandler *handler, xmlBufferPtr out, xmlBufferPtr in); XMLPUBFUN int XMLCALL xmlCharEncInFunc (xmlCharEncodingHandler *handler, xmlBufferPtr out, xmlBufferPtr in); XMLPUBFUN int XMLCALL xmlCharEncFirstLine (xmlCharEncodingHandler *handler, xmlBufferPtr out, xmlBufferPtr in); XMLPUBFUN int XMLCALL xmlCharEncCloseFunc (xmlCharEncodingHandler *handler); /* * Export a few useful functions */ #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN int XMLCALL UTF8Toisolat1 (unsigned char *out, int *outlen, const unsigned char *in, int *inlen); #endif /* LIBXML_OUTPUT_ENABLED */ XMLPUBFUN int XMLCALL isolat1ToUTF8 (unsigned char *out, int *outlen, const unsigned char *in, int *inlen); #ifdef __cplusplus } #endif #endif /* __XML_CHAR_ENCODING_H__ */ PK!#S))libxml/xmlIO.hnu[/* * Summary: interface for the I/O interfaces used by the parser * Description: interface for the I/O interfaces used by the parser * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_IO_H__ #define __XML_IO_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* * Those are the functions and datatypes for the parser input * I/O structures. */ /** * xmlInputMatchCallback: * @filename: the filename or URI * * Callback used in the I/O Input API to detect if the current handler * can provide input functionality for this resource. * * Returns 1 if yes and 0 if another Input module should be used */ typedef int (XMLCALL *xmlInputMatchCallback) (char const *filename); /** * xmlInputOpenCallback: * @filename: the filename or URI * * Callback used in the I/O Input API to open the resource * * Returns an Input context or NULL in case or error */ typedef void * (XMLCALL *xmlInputOpenCallback) (char const *filename); /** * xmlInputReadCallback: * @context: an Input context * @buffer: the buffer to store data read * @len: the length of the buffer in bytes * * Callback used in the I/O Input API to read the resource * * Returns the number of bytes read or -1 in case of error */ typedef int (XMLCALL *xmlInputReadCallback) (void * context, char * buffer, int len); /** * xmlInputCloseCallback: * @context: an Input context * * Callback used in the I/O Input API to close the resource * * Returns 0 or -1 in case of error */ typedef int (XMLCALL *xmlInputCloseCallback) (void * context); #ifdef LIBXML_OUTPUT_ENABLED /* * Those are the functions and datatypes for the library output * I/O structures. */ /** * xmlOutputMatchCallback: * @filename: the filename or URI * * Callback used in the I/O Output API to detect if the current handler * can provide output functionality for this resource. * * Returns 1 if yes and 0 if another Output module should be used */ typedef int (XMLCALL *xmlOutputMatchCallback) (char const *filename); /** * xmlOutputOpenCallback: * @filename: the filename or URI * * Callback used in the I/O Output API to open the resource * * Returns an Output context or NULL in case or error */ typedef void * (XMLCALL *xmlOutputOpenCallback) (char const *filename); /** * xmlOutputWriteCallback: * @context: an Output context * @buffer: the buffer of data to write * @len: the length of the buffer in bytes * * Callback used in the I/O Output API to write to the resource * * Returns the number of bytes written or -1 in case of error */ typedef int (XMLCALL *xmlOutputWriteCallback) (void * context, const char * buffer, int len); /** * xmlOutputCloseCallback: * @context: an Output context * * Callback used in the I/O Output API to close the resource * * Returns 0 or -1 in case of error */ typedef int (XMLCALL *xmlOutputCloseCallback) (void * context); #endif /* LIBXML_OUTPUT_ENABLED */ #ifdef __cplusplus } #endif #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct _xmlParserInputBuffer { void* context; xmlInputReadCallback readcallback; xmlInputCloseCallback closecallback; xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ xmlBufPtr buffer; /* Local buffer encoded in UTF-8 */ xmlBufPtr raw; /* if encoder != NULL buffer for raw input */ int compressed; /* -1=unknown, 0=not compressed, 1=compressed */ int error; unsigned long rawconsumed;/* amount consumed from raw */ }; #ifdef LIBXML_OUTPUT_ENABLED struct _xmlOutputBuffer { void* context; xmlOutputWriteCallback writecallback; xmlOutputCloseCallback closecallback; xmlCharEncodingHandlerPtr encoder; /* I18N conversions to UTF-8 */ xmlBufPtr buffer; /* Local buffer encoded in UTF-8 or ISOLatin */ xmlBufPtr conv; /* if encoder != NULL buffer for output */ int written; /* total number of byte written */ int error; }; #endif /* LIBXML_OUTPUT_ENABLED */ /* * Interfaces for input */ XMLPUBFUN void XMLCALL xmlCleanupInputCallbacks (void); XMLPUBFUN int XMLCALL xmlPopInputCallbacks (void); XMLPUBFUN void XMLCALL xmlRegisterDefaultInputCallbacks (void); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlAllocParserInputBuffer (xmlCharEncoding enc); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateFilename (const char *URI, xmlCharEncoding enc); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateFile (FILE *file, xmlCharEncoding enc); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateFd (int fd, xmlCharEncoding enc); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateMem (const char *mem, int size, xmlCharEncoding enc); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateStatic (const char *mem, int size, xmlCharEncoding enc); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlParserInputBufferCreateIO (xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc); XMLPUBFUN int XMLCALL xmlParserInputBufferRead (xmlParserInputBufferPtr in, int len); XMLPUBFUN int XMLCALL xmlParserInputBufferGrow (xmlParserInputBufferPtr in, int len); XMLPUBFUN int XMLCALL xmlParserInputBufferPush (xmlParserInputBufferPtr in, int len, const char *buf); XMLPUBFUN void XMLCALL xmlFreeParserInputBuffer (xmlParserInputBufferPtr in); XMLPUBFUN char * XMLCALL xmlParserGetDirectory (const char *filename); XMLPUBFUN int XMLCALL xmlRegisterInputCallbacks (xmlInputMatchCallback matchFunc, xmlInputOpenCallback openFunc, xmlInputReadCallback readFunc, xmlInputCloseCallback closeFunc); xmlParserInputBufferPtr __xmlParserInputBufferCreateFilename(const char *URI, xmlCharEncoding enc); #ifdef LIBXML_OUTPUT_ENABLED /* * Interfaces for output */ XMLPUBFUN void XMLCALL xmlCleanupOutputCallbacks (void); XMLPUBFUN int XMLCALL xmlPopOutputCallbacks (void); XMLPUBFUN void XMLCALL xmlRegisterDefaultOutputCallbacks(void); XMLPUBFUN xmlOutputBufferPtr XMLCALL xmlAllocOutputBuffer (xmlCharEncodingHandlerPtr encoder); XMLPUBFUN xmlOutputBufferPtr XMLCALL xmlOutputBufferCreateFilename (const char *URI, xmlCharEncodingHandlerPtr encoder, int compression); XMLPUBFUN xmlOutputBufferPtr XMLCALL xmlOutputBufferCreateFile (FILE *file, xmlCharEncodingHandlerPtr encoder); XMLPUBFUN xmlOutputBufferPtr XMLCALL xmlOutputBufferCreateBuffer (xmlBufferPtr buffer, xmlCharEncodingHandlerPtr encoder); XMLPUBFUN xmlOutputBufferPtr XMLCALL xmlOutputBufferCreateFd (int fd, xmlCharEncodingHandlerPtr encoder); XMLPUBFUN xmlOutputBufferPtr XMLCALL xmlOutputBufferCreateIO (xmlOutputWriteCallback iowrite, xmlOutputCloseCallback ioclose, void *ioctx, xmlCharEncodingHandlerPtr encoder); /* Couple of APIs to get the output without digging into the buffers */ XMLPUBFUN const xmlChar * XMLCALL xmlOutputBufferGetContent (xmlOutputBufferPtr out); XMLPUBFUN size_t XMLCALL xmlOutputBufferGetSize (xmlOutputBufferPtr out); XMLPUBFUN int XMLCALL xmlOutputBufferWrite (xmlOutputBufferPtr out, int len, const char *buf); XMLPUBFUN int XMLCALL xmlOutputBufferWriteString (xmlOutputBufferPtr out, const char *str); XMLPUBFUN int XMLCALL xmlOutputBufferWriteEscape (xmlOutputBufferPtr out, const xmlChar *str, xmlCharEncodingOutputFunc escaping); XMLPUBFUN int XMLCALL xmlOutputBufferFlush (xmlOutputBufferPtr out); XMLPUBFUN int XMLCALL xmlOutputBufferClose (xmlOutputBufferPtr out); XMLPUBFUN int XMLCALL xmlRegisterOutputCallbacks (xmlOutputMatchCallback matchFunc, xmlOutputOpenCallback openFunc, xmlOutputWriteCallback writeFunc, xmlOutputCloseCallback closeFunc); xmlOutputBufferPtr __xmlOutputBufferCreateFilename(const char *URI, xmlCharEncodingHandlerPtr encoder, int compression); #ifdef LIBXML_HTTP_ENABLED /* This function only exists if HTTP support built into the library */ XMLPUBFUN void XMLCALL xmlRegisterHTTPPostCallbacks (void ); #endif /* LIBXML_HTTP_ENABLED */ #endif /* LIBXML_OUTPUT_ENABLED */ XMLPUBFUN xmlParserInputPtr XMLCALL xmlCheckHTTPInput (xmlParserCtxtPtr ctxt, xmlParserInputPtr ret); /* * A predefined entity loader disabling network accesses */ XMLPUBFUN xmlParserInputPtr XMLCALL xmlNoNetExternalEntityLoader (const char *URL, const char *ID, xmlParserCtxtPtr ctxt); /* * xmlNormalizeWindowsPath is obsolete, don't use it. * Check xmlCanonicPath in uri.h for a better alternative. */ XMLPUBFUN xmlChar * XMLCALL xmlNormalizeWindowsPath (const xmlChar *path); XMLPUBFUN int XMLCALL xmlCheckFilename (const char *path); /** * Default 'file://' protocol callbacks */ XMLPUBFUN int XMLCALL xmlFileMatch (const char *filename); XMLPUBFUN void * XMLCALL xmlFileOpen (const char *filename); XMLPUBFUN int XMLCALL xmlFileRead (void * context, char * buffer, int len); XMLPUBFUN int XMLCALL xmlFileClose (void * context); /** * Default 'http://' protocol callbacks */ #ifdef LIBXML_HTTP_ENABLED XMLPUBFUN int XMLCALL xmlIOHTTPMatch (const char *filename); XMLPUBFUN void * XMLCALL xmlIOHTTPOpen (const char *filename); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void * XMLCALL xmlIOHTTPOpenW (const char * post_uri, int compression ); #endif /* LIBXML_OUTPUT_ENABLED */ XMLPUBFUN int XMLCALL xmlIOHTTPRead (void * context, char * buffer, int len); XMLPUBFUN int XMLCALL xmlIOHTTPClose (void * context); #endif /* LIBXML_HTTP_ENABLED */ /** * Default 'ftp://' protocol callbacks */ #ifdef LIBXML_FTP_ENABLED XMLPUBFUN int XMLCALL xmlIOFTPMatch (const char *filename); XMLPUBFUN void * XMLCALL xmlIOFTPOpen (const char *filename); XMLPUBFUN int XMLCALL xmlIOFTPRead (void * context, char * buffer, int len); XMLPUBFUN int XMLCALL xmlIOFTPClose (void * context); #endif /* LIBXML_FTP_ENABLED */ #ifdef __cplusplus } #endif #endif /* __XML_IO_H__ */ PK!ڃ libxml/hash.hnu[/* * Summary: Chained hash tables * Description: This module implements the hash table support used in * various places in the library. * * Copy: See Copyright for the status of this software. * * Author: Bjorn Reese */ #ifndef __XML_HASH_H__ #define __XML_HASH_H__ #ifdef __cplusplus extern "C" { #endif /* * The hash table. */ typedef struct _xmlHashTable xmlHashTable; typedef xmlHashTable *xmlHashTablePtr; #ifdef __cplusplus } #endif #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Recent version of gcc produce a warning when a function pointer is assigned * to an object pointer, or vice versa. The following macro is a dirty hack * to allow suppression of the warning. If your architecture has function * pointers which are a different size than a void pointer, there may be some * serious trouble within the library. */ /** * XML_CAST_FPTR: * @fptr: pointer to a function * * Macro to do a casting from an object pointer to a * function pointer without encountering a warning from * gcc * * #define XML_CAST_FPTR(fptr) (*(void **)(&fptr)) * This macro violated ISO C aliasing rules (gcc4 on s390 broke) * so it is disabled now */ #define XML_CAST_FPTR(fptr) fptr /* * function types: */ /** * xmlHashDeallocator: * @payload: the data in the hash * @name: the name associated * * Callback to free data from a hash. */ typedef void (*xmlHashDeallocator)(void *payload, const xmlChar *name); /** * xmlHashCopier: * @payload: the data in the hash * @name: the name associated * * Callback to copy data from a hash. * * Returns a copy of the data or NULL in case of error. */ typedef void *(*xmlHashCopier)(void *payload, const xmlChar *name); /** * xmlHashScanner: * @payload: the data in the hash * @data: extra scanner data * @name: the name associated * * Callback when scanning data in a hash with the simple scanner. */ typedef void (*xmlHashScanner)(void *payload, void *data, const xmlChar *name); /** * xmlHashScannerFull: * @payload: the data in the hash * @data: extra scanner data * @name: the name associated * @name2: the second name associated * @name3: the third name associated * * Callback when scanning data in a hash with the full scanner. */ typedef void (*xmlHashScannerFull)(void *payload, void *data, const xmlChar *name, const xmlChar *name2, const xmlChar *name3); /* * Constructor and destructor. */ XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreate (int size); XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCreateDict(int size, xmlDictPtr dict); XMLPUBFUN void XMLCALL xmlHashFree (xmlHashTablePtr table, xmlHashDeallocator f); XMLPUBFUN void XMLCALL xmlHashDefaultDeallocator(void *entry, const xmlChar *name); /* * Add a new entry to the hash table. */ XMLPUBFUN int XMLCALL xmlHashAddEntry (xmlHashTablePtr table, const xmlChar *name, void *userdata); XMLPUBFUN int XMLCALL xmlHashUpdateEntry(xmlHashTablePtr table, const xmlChar *name, void *userdata, xmlHashDeallocator f); XMLPUBFUN int XMLCALL xmlHashAddEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata); XMLPUBFUN int XMLCALL xmlHashUpdateEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, void *userdata, xmlHashDeallocator f); XMLPUBFUN int XMLCALL xmlHashAddEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata); XMLPUBFUN int XMLCALL xmlHashUpdateEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, void *userdata, xmlHashDeallocator f); /* * Remove an entry from the hash table. */ XMLPUBFUN int XMLCALL xmlHashRemoveEntry(xmlHashTablePtr table, const xmlChar *name, xmlHashDeallocator f); XMLPUBFUN int XMLCALL xmlHashRemoveEntry2(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, xmlHashDeallocator f); XMLPUBFUN int XMLCALL xmlHashRemoveEntry3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, xmlHashDeallocator f); /* * Retrieve the userdata. */ XMLPUBFUN void * XMLCALL xmlHashLookup (xmlHashTablePtr table, const xmlChar *name); XMLPUBFUN void * XMLCALL xmlHashLookup2 (xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2); XMLPUBFUN void * XMLCALL xmlHashLookup3 (xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3); XMLPUBFUN void * XMLCALL xmlHashQLookup (xmlHashTablePtr table, const xmlChar *name, const xmlChar *prefix); XMLPUBFUN void * XMLCALL xmlHashQLookup2 (xmlHashTablePtr table, const xmlChar *name, const xmlChar *prefix, const xmlChar *name2, const xmlChar *prefix2); XMLPUBFUN void * XMLCALL xmlHashQLookup3 (xmlHashTablePtr table, const xmlChar *name, const xmlChar *prefix, const xmlChar *name2, const xmlChar *prefix2, const xmlChar *name3, const xmlChar *prefix3); /* * Helpers. */ XMLPUBFUN xmlHashTablePtr XMLCALL xmlHashCopy (xmlHashTablePtr table, xmlHashCopier f); XMLPUBFUN int XMLCALL xmlHashSize (xmlHashTablePtr table); XMLPUBFUN void XMLCALL xmlHashScan (xmlHashTablePtr table, xmlHashScanner f, void *data); XMLPUBFUN void XMLCALL xmlHashScan3 (xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, xmlHashScanner f, void *data); XMLPUBFUN void XMLCALL xmlHashScanFull (xmlHashTablePtr table, xmlHashScannerFull f, void *data); XMLPUBFUN void XMLCALL xmlHashScanFull3(xmlHashTablePtr table, const xmlChar *name, const xmlChar *name2, const xmlChar *name3, xmlHashScannerFull f, void *data); #ifdef __cplusplus } #endif #endif /* ! __XML_HASH_H__ */ PK! libxml/threads.hnu[/** * Summary: interfaces for thread handling * Description: set of generic threading related routines * should work with pthreads, Windows native or TLS threads * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_THREADS_H__ #define __XML_THREADS_H__ #include #ifdef __cplusplus extern "C" { #endif /* * xmlMutex are a simple mutual exception locks. */ typedef struct _xmlMutex xmlMutex; typedef xmlMutex *xmlMutexPtr; /* * xmlRMutex are reentrant mutual exception locks. */ typedef struct _xmlRMutex xmlRMutex; typedef xmlRMutex *xmlRMutexPtr; #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif XMLPUBFUN xmlMutexPtr XMLCALL xmlNewMutex (void); XMLPUBFUN void XMLCALL xmlMutexLock (xmlMutexPtr tok); XMLPUBFUN void XMLCALL xmlMutexUnlock (xmlMutexPtr tok); XMLPUBFUN void XMLCALL xmlFreeMutex (xmlMutexPtr tok); XMLPUBFUN xmlRMutexPtr XMLCALL xmlNewRMutex (void); XMLPUBFUN void XMLCALL xmlRMutexLock (xmlRMutexPtr tok); XMLPUBFUN void XMLCALL xmlRMutexUnlock (xmlRMutexPtr tok); XMLPUBFUN void XMLCALL xmlFreeRMutex (xmlRMutexPtr tok); /* * Library wide APIs. */ XMLPUBFUN void XMLCALL xmlInitThreads (void); XMLPUBFUN void XMLCALL xmlLockLibrary (void); XMLPUBFUN void XMLCALL xmlUnlockLibrary(void); XMLPUBFUN int XMLCALL xmlGetThreadId (void); XMLPUBFUN int XMLCALL xmlIsMainThread (void); XMLPUBFUN void XMLCALL xmlCleanupThreads(void); XMLPUBFUN xmlGlobalStatePtr XMLCALL xmlGetGlobalState(void); #ifdef HAVE_PTHREAD_H #elif defined(HAVE_WIN32_THREADS) && !defined(HAVE_COMPILER_TLS) && (!defined(LIBXML_STATIC) || defined(LIBXML_STATIC_FOR_DLL)) #if defined(LIBXML_STATIC_FOR_DLL) int XMLCALL xmlDllMain(void *hinstDLL, unsigned long fdwReason, void *lpvReserved); #endif #endif #ifdef __cplusplus } #endif #endif /* __XML_THREADS_H__ */ PK!)$$libxml/HTMLparser.hnu[/* * Summary: interface for an HTML 4.0 non-verifying parser * Description: this module implements an HTML 4.0 non-verifying parser * with API compatible with the XML parser ones. It should * be able to parse "real world" HTML, even if severely * broken from a specification point of view. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __HTML_PARSER_H__ #define __HTML_PARSER_H__ #include #include #ifdef LIBXML_HTML_ENABLED #ifdef __cplusplus extern "C" { #endif /* * Most of the back-end structures from XML and HTML are shared. */ typedef xmlParserCtxt htmlParserCtxt; typedef xmlParserCtxtPtr htmlParserCtxtPtr; typedef xmlParserNodeInfo htmlParserNodeInfo; typedef xmlSAXHandler htmlSAXHandler; typedef xmlSAXHandlerPtr htmlSAXHandlerPtr; typedef xmlParserInput htmlParserInput; typedef xmlParserInputPtr htmlParserInputPtr; typedef xmlDocPtr htmlDocPtr; typedef xmlNodePtr htmlNodePtr; /* * Internal description of an HTML element, representing HTML 4.01 * and XHTML 1.0 (which share the same structure). */ typedef struct _htmlElemDesc htmlElemDesc; typedef htmlElemDesc *htmlElemDescPtr; struct _htmlElemDesc { const char *name; /* The tag name */ char startTag; /* Whether the start tag can be implied */ char endTag; /* Whether the end tag can be implied */ char saveEndTag; /* Whether the end tag should be saved */ char empty; /* Is this an empty element ? */ char depr; /* Is this a deprecated element ? */ char dtd; /* 1: only in Loose DTD, 2: only Frameset one */ char isinline; /* is this a block 0 or inline 1 element */ const char *desc; /* the description */ /* NRK Jan.2003 * New fields encapsulating HTML structure * * Bugs: * This is a very limited representation. It fails to tell us when * an element *requires* subelements (we only have whether they're * allowed or not), and it doesn't tell us where CDATA and PCDATA * are allowed. Some element relationships are not fully represented: * these are flagged with the word MODIFIER */ const char** subelts; /* allowed sub-elements of this element */ const char* defaultsubelt; /* subelement for suggested auto-repair if necessary or NULL */ const char** attrs_opt; /* Optional Attributes */ const char** attrs_depr; /* Additional deprecated attributes */ const char** attrs_req; /* Required attributes */ }; /* * Internal description of an HTML entity. */ typedef struct _htmlEntityDesc htmlEntityDesc; typedef htmlEntityDesc *htmlEntityDescPtr; struct _htmlEntityDesc { unsigned int value; /* the UNICODE value for the character */ const char *name; /* The entity name */ const char *desc; /* the description */ }; /* * There is only few public functions. */ XMLPUBFUN const htmlElemDesc * XMLCALL htmlTagLookup (const xmlChar *tag); XMLPUBFUN const htmlEntityDesc * XMLCALL htmlEntityLookup(const xmlChar *name); XMLPUBFUN const htmlEntityDesc * XMLCALL htmlEntityValueLookup(unsigned int value); XMLPUBFUN int XMLCALL htmlIsAutoClosed(htmlDocPtr doc, htmlNodePtr elem); XMLPUBFUN int XMLCALL htmlAutoCloseTag(htmlDocPtr doc, const xmlChar *name, htmlNodePtr elem); XMLPUBFUN const htmlEntityDesc * XMLCALL htmlParseEntityRef(htmlParserCtxtPtr ctxt, const xmlChar **str); XMLPUBFUN int XMLCALL htmlParseCharRef(htmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL htmlParseElement(htmlParserCtxtPtr ctxt); XMLPUBFUN htmlParserCtxtPtr XMLCALL htmlNewParserCtxt(void); XMLPUBFUN htmlParserCtxtPtr XMLCALL htmlCreateMemoryParserCtxt(const char *buffer, int size); XMLPUBFUN int XMLCALL htmlParseDocument(htmlParserCtxtPtr ctxt); XMLPUBFUN htmlDocPtr XMLCALL htmlSAXParseDoc (const xmlChar *cur, const char *encoding, htmlSAXHandlerPtr sax, void *userData); XMLPUBFUN htmlDocPtr XMLCALL htmlParseDoc (const xmlChar *cur, const char *encoding); XMLPUBFUN htmlDocPtr XMLCALL htmlSAXParseFile(const char *filename, const char *encoding, htmlSAXHandlerPtr sax, void *userData); XMLPUBFUN htmlDocPtr XMLCALL htmlParseFile (const char *filename, const char *encoding); XMLPUBFUN int XMLCALL UTF8ToHtml (unsigned char *out, int *outlen, const unsigned char *in, int *inlen); XMLPUBFUN int XMLCALL htmlEncodeEntities(unsigned char *out, int *outlen, const unsigned char *in, int *inlen, int quoteChar); XMLPUBFUN int XMLCALL htmlIsScriptAttribute(const xmlChar *name); XMLPUBFUN int XMLCALL htmlHandleOmittedElem(int val); #ifdef LIBXML_PUSH_ENABLED /** * Interfaces for the Push mode. */ XMLPUBFUN htmlParserCtxtPtr XMLCALL htmlCreatePushParserCtxt(htmlSAXHandlerPtr sax, void *user_data, const char *chunk, int size, const char *filename, xmlCharEncoding enc); XMLPUBFUN int XMLCALL htmlParseChunk (htmlParserCtxtPtr ctxt, const char *chunk, int size, int terminate); #endif /* LIBXML_PUSH_ENABLED */ XMLPUBFUN void XMLCALL htmlFreeParserCtxt (htmlParserCtxtPtr ctxt); /* * New set of simpler/more flexible APIs */ /** * xmlParserOption: * * This is the set of XML parser options that can be passed down * to the xmlReadDoc() and similar calls. */ typedef enum { HTML_PARSE_RECOVER = 1<<0, /* Relaxed parsing */ HTML_PARSE_NODEFDTD = 1<<2, /* do not default a doctype if not found */ HTML_PARSE_NOERROR = 1<<5, /* suppress error reports */ HTML_PARSE_NOWARNING= 1<<6, /* suppress warning reports */ HTML_PARSE_PEDANTIC = 1<<7, /* pedantic error reporting */ HTML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */ HTML_PARSE_NONET = 1<<11,/* Forbid network access */ HTML_PARSE_NOIMPLIED= 1<<13,/* Do not add implied html/body... elements */ HTML_PARSE_COMPACT = 1<<16,/* compact small text nodes */ HTML_PARSE_IGNORE_ENC=1<<21 /* ignore internal document encoding hint */ } htmlParserOption; XMLPUBFUN void XMLCALL htmlCtxtReset (htmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL htmlCtxtUseOptions (htmlParserCtxtPtr ctxt, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlReadDoc (const xmlChar *cur, const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlReadFile (const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlReadMemory (const char *buffer, int size, const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlReadFd (int fd, const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlReadIO (xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlCtxtReadDoc (xmlParserCtxtPtr ctxt, const xmlChar *cur, const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlCtxtReadFile (xmlParserCtxtPtr ctxt, const char *filename, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlCtxtReadMemory (xmlParserCtxtPtr ctxt, const char *buffer, int size, const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlCtxtReadFd (xmlParserCtxtPtr ctxt, int fd, const char *URL, const char *encoding, int options); XMLPUBFUN htmlDocPtr XMLCALL htmlCtxtReadIO (xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options); /* NRK/Jan2003: further knowledge of HTML structure */ typedef enum { HTML_NA = 0 , /* something we don't check at all */ HTML_INVALID = 0x1 , HTML_DEPRECATED = 0x2 , HTML_VALID = 0x4 , HTML_REQUIRED = 0xc /* VALID bit set so ( & HTML_VALID ) is TRUE */ } htmlStatus ; /* Using htmlElemDesc rather than name here, to emphasise the fact that otherwise there's a lookup overhead */ XMLPUBFUN htmlStatus XMLCALL htmlAttrAllowed(const htmlElemDesc*, const xmlChar*, int) ; XMLPUBFUN int XMLCALL htmlElementAllowedHere(const htmlElemDesc*, const xmlChar*) ; XMLPUBFUN htmlStatus XMLCALL htmlElementStatusHere(const htmlElemDesc*, const htmlElemDesc*) ; XMLPUBFUN htmlStatus XMLCALL htmlNodeStatus(const htmlNodePtr, int) ; /** * htmlDefaultSubelement: * @elt: HTML element * * Returns the default subelement for this element */ #define htmlDefaultSubelement(elt) elt->defaultsubelt /** * htmlElementAllowedHereDesc: * @parent: HTML parent element * @elt: HTML element * * Checks whether an HTML element description may be a * direct child of the specified element. * * Returns 1 if allowed; 0 otherwise. */ #define htmlElementAllowedHereDesc(parent,elt) \ htmlElementAllowedHere((parent), (elt)->name) /** * htmlRequiredAttrs: * @elt: HTML element * * Returns the attributes required for the specified element. */ #define htmlRequiredAttrs(elt) (elt)->attrs_req #ifdef __cplusplus } #endif #endif /* LIBXML_HTML_ENABLED */ #endif /* __HTML_PARSER_H__ */ PK!eGHlibxml/nanoftp.hnu[/* * Summary: minimal FTP implementation * Description: minimal FTP implementation allowing to fetch resources * like external subset. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __NANO_FTP_H__ #define __NANO_FTP_H__ #include #ifdef LIBXML_FTP_ENABLED /* Needed for portability to Windows 64 bits */ #if defined(_WIN32) && !defined(__CYGWIN__) #include #else /** * SOCKET: * * macro used to provide portability of code to windows sockets */ #define SOCKET int /** * INVALID_SOCKET: * * macro used to provide portability of code to windows sockets * the value to be used when the socket is not valid */ #undef INVALID_SOCKET #define INVALID_SOCKET (-1) #endif #ifdef __cplusplus extern "C" { #endif /** * ftpListCallback: * @userData: user provided data for the callback * @filename: the file name (including "->" when links are shown) * @attrib: the attribute string * @owner: the owner string * @group: the group string * @size: the file size * @links: the link count * @year: the year * @month: the month * @day: the day * @hour: the hour * @minute: the minute * * A callback for the xmlNanoFTPList command. * Note that only one of year and day:minute are specified. */ typedef void (*ftpListCallback) (void *userData, const char *filename, const char *attrib, const char *owner, const char *group, unsigned long size, int links, int year, const char *month, int day, int hour, int minute); /** * ftpDataCallback: * @userData: the user provided context * @data: the data received * @len: its size in bytes * * A callback for the xmlNanoFTPGet command. */ typedef void (*ftpDataCallback) (void *userData, const char *data, int len); /* * Init */ XMLPUBFUN void XMLCALL xmlNanoFTPInit (void); XMLPUBFUN void XMLCALL xmlNanoFTPCleanup (void); /* * Creating/freeing contexts. */ XMLPUBFUN void * XMLCALL xmlNanoFTPNewCtxt (const char *URL); XMLPUBFUN void XMLCALL xmlNanoFTPFreeCtxt (void * ctx); XMLPUBFUN void * XMLCALL xmlNanoFTPConnectTo (const char *server, int port); /* * Opening/closing session connections. */ XMLPUBFUN void * XMLCALL xmlNanoFTPOpen (const char *URL); XMLPUBFUN int XMLCALL xmlNanoFTPConnect (void *ctx); XMLPUBFUN int XMLCALL xmlNanoFTPClose (void *ctx); XMLPUBFUN int XMLCALL xmlNanoFTPQuit (void *ctx); XMLPUBFUN void XMLCALL xmlNanoFTPScanProxy (const char *URL); XMLPUBFUN void XMLCALL xmlNanoFTPProxy (const char *host, int port, const char *user, const char *passwd, int type); XMLPUBFUN int XMLCALL xmlNanoFTPUpdateURL (void *ctx, const char *URL); /* * Rather internal commands. */ XMLPUBFUN int XMLCALL xmlNanoFTPGetResponse (void *ctx); XMLPUBFUN int XMLCALL xmlNanoFTPCheckResponse (void *ctx); /* * CD/DIR/GET handlers. */ XMLPUBFUN int XMLCALL xmlNanoFTPCwd (void *ctx, const char *directory); XMLPUBFUN int XMLCALL xmlNanoFTPDele (void *ctx, const char *file); XMLPUBFUN SOCKET XMLCALL xmlNanoFTPGetConnection (void *ctx); XMLPUBFUN int XMLCALL xmlNanoFTPCloseConnection(void *ctx); XMLPUBFUN int XMLCALL xmlNanoFTPList (void *ctx, ftpListCallback callback, void *userData, const char *filename); XMLPUBFUN SOCKET XMLCALL xmlNanoFTPGetSocket (void *ctx, const char *filename); XMLPUBFUN int XMLCALL xmlNanoFTPGet (void *ctx, ftpDataCallback callback, void *userData, const char *filename); XMLPUBFUN int XMLCALL xmlNanoFTPRead (void *ctx, void *dest, int len); #ifdef __cplusplus } #endif #endif /* LIBXML_FTP_ENABLED */ #endif /* __NANO_FTP_H__ */ PK!lllibxml/relaxng.hnu[/* * Summary: implementation of the Relax-NG validation * Description: implementation of the Relax-NG validation * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_RELAX_NG__ #define __XML_RELAX_NG__ #include #include #include #ifdef LIBXML_SCHEMAS_ENABLED #ifdef __cplusplus extern "C" { #endif typedef struct _xmlRelaxNG xmlRelaxNG; typedef xmlRelaxNG *xmlRelaxNGPtr; /** * xmlRelaxNGValidityErrorFunc: * @ctx: the validation context * @msg: the message * @...: extra arguments * * Signature of an error callback from a Relax-NG validation */ typedef void (XMLCDECL *xmlRelaxNGValidityErrorFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * xmlRelaxNGValidityWarningFunc: * @ctx: the validation context * @msg: the message * @...: extra arguments * * Signature of a warning callback from a Relax-NG validation */ typedef void (XMLCDECL *xmlRelaxNGValidityWarningFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * A schemas validation context */ typedef struct _xmlRelaxNGParserCtxt xmlRelaxNGParserCtxt; typedef xmlRelaxNGParserCtxt *xmlRelaxNGParserCtxtPtr; typedef struct _xmlRelaxNGValidCtxt xmlRelaxNGValidCtxt; typedef xmlRelaxNGValidCtxt *xmlRelaxNGValidCtxtPtr; /* * xmlRelaxNGValidErr: * * List of possible Relax NG validation errors */ typedef enum { XML_RELAXNG_OK = 0, XML_RELAXNG_ERR_MEMORY, XML_RELAXNG_ERR_TYPE, XML_RELAXNG_ERR_TYPEVAL, XML_RELAXNG_ERR_DUPID, XML_RELAXNG_ERR_TYPECMP, XML_RELAXNG_ERR_NOSTATE, XML_RELAXNG_ERR_NODEFINE, XML_RELAXNG_ERR_LISTEXTRA, XML_RELAXNG_ERR_LISTEMPTY, XML_RELAXNG_ERR_INTERNODATA, XML_RELAXNG_ERR_INTERSEQ, XML_RELAXNG_ERR_INTEREXTRA, XML_RELAXNG_ERR_ELEMNAME, XML_RELAXNG_ERR_ATTRNAME, XML_RELAXNG_ERR_ELEMNONS, XML_RELAXNG_ERR_ATTRNONS, XML_RELAXNG_ERR_ELEMWRONGNS, XML_RELAXNG_ERR_ATTRWRONGNS, XML_RELAXNG_ERR_ELEMEXTRANS, XML_RELAXNG_ERR_ATTREXTRANS, XML_RELAXNG_ERR_ELEMNOTEMPTY, XML_RELAXNG_ERR_NOELEM, XML_RELAXNG_ERR_NOTELEM, XML_RELAXNG_ERR_ATTRVALID, XML_RELAXNG_ERR_CONTENTVALID, XML_RELAXNG_ERR_EXTRACONTENT, XML_RELAXNG_ERR_INVALIDATTR, XML_RELAXNG_ERR_DATAELEM, XML_RELAXNG_ERR_VALELEM, XML_RELAXNG_ERR_LISTELEM, XML_RELAXNG_ERR_DATATYPE, XML_RELAXNG_ERR_VALUE, XML_RELAXNG_ERR_LIST, XML_RELAXNG_ERR_NOGRAMMAR, XML_RELAXNG_ERR_EXTRADATA, XML_RELAXNG_ERR_LACKDATA, XML_RELAXNG_ERR_INTERNAL, XML_RELAXNG_ERR_ELEMWRONG, XML_RELAXNG_ERR_TEXTWRONG } xmlRelaxNGValidErr; /* * xmlRelaxNGParserFlags: * * List of possible Relax NG Parser flags */ typedef enum { XML_RELAXNGP_NONE = 0, XML_RELAXNGP_FREE_DOC = 1, XML_RELAXNGP_CRNG = 2 } xmlRelaxNGParserFlag; XMLPUBFUN int XMLCALL xmlRelaxNGInitTypes (void); XMLPUBFUN void XMLCALL xmlRelaxNGCleanupTypes (void); /* * Interfaces for parsing. */ XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL xmlRelaxNGNewParserCtxt (const char *URL); XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL xmlRelaxNGNewMemParserCtxt (const char *buffer, int size); XMLPUBFUN xmlRelaxNGParserCtxtPtr XMLCALL xmlRelaxNGNewDocParserCtxt (xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlRelaxParserSetFlag (xmlRelaxNGParserCtxtPtr ctxt, int flag); XMLPUBFUN void XMLCALL xmlRelaxNGFreeParserCtxt (xmlRelaxNGParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlRelaxNGSetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGValidityErrorFunc err, xmlRelaxNGValidityWarningFunc warn, void *ctx); XMLPUBFUN int XMLCALL xmlRelaxNGGetParserErrors(xmlRelaxNGParserCtxtPtr ctxt, xmlRelaxNGValidityErrorFunc *err, xmlRelaxNGValidityWarningFunc *warn, void **ctx); XMLPUBFUN void XMLCALL xmlRelaxNGSetParserStructuredErrors( xmlRelaxNGParserCtxtPtr ctxt, xmlStructuredErrorFunc serror, void *ctx); XMLPUBFUN xmlRelaxNGPtr XMLCALL xmlRelaxNGParse (xmlRelaxNGParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlRelaxNGFree (xmlRelaxNGPtr schema); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlRelaxNGDump (FILE *output, xmlRelaxNGPtr schema); XMLPUBFUN void XMLCALL xmlRelaxNGDumpTree (FILE * output, xmlRelaxNGPtr schema); #endif /* LIBXML_OUTPUT_ENABLED */ /* * Interfaces for validating */ XMLPUBFUN void XMLCALL xmlRelaxNGSetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidityErrorFunc err, xmlRelaxNGValidityWarningFunc warn, void *ctx); XMLPUBFUN int XMLCALL xmlRelaxNGGetValidErrors(xmlRelaxNGValidCtxtPtr ctxt, xmlRelaxNGValidityErrorFunc *err, xmlRelaxNGValidityWarningFunc *warn, void **ctx); XMLPUBFUN void XMLCALL xmlRelaxNGSetValidStructuredErrors(xmlRelaxNGValidCtxtPtr ctxt, xmlStructuredErrorFunc serror, void *ctx); XMLPUBFUN xmlRelaxNGValidCtxtPtr XMLCALL xmlRelaxNGNewValidCtxt (xmlRelaxNGPtr schema); XMLPUBFUN void XMLCALL xmlRelaxNGFreeValidCtxt (xmlRelaxNGValidCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlRelaxNGValidateDoc (xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc); /* * Interfaces for progressive validation when possible */ XMLPUBFUN int XMLCALL xmlRelaxNGValidatePushElement (xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem); XMLPUBFUN int XMLCALL xmlRelaxNGValidatePushCData (xmlRelaxNGValidCtxtPtr ctxt, const xmlChar *data, int len); XMLPUBFUN int XMLCALL xmlRelaxNGValidatePopElement (xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem); XMLPUBFUN int XMLCALL xmlRelaxNGValidateFullElement (xmlRelaxNGValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem); #ifdef __cplusplus } #endif #endif /* LIBXML_SCHEMAS_ENABLED */ #endif /* __XML_RELAX_NG__ */ PK!}" libxml/dict.hnu[/* * Summary: string dictionary * Description: dictionary of reusable strings, just used to avoid allocation * and freeing operations. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_DICT_H__ #define __XML_DICT_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* * The dictionary. */ typedef struct _xmlDict xmlDict; typedef xmlDict *xmlDictPtr; /* * Initializer */ XMLPUBFUN int XMLCALL xmlInitializeDict(void); /* * Constructor and destructor. */ XMLPUBFUN xmlDictPtr XMLCALL xmlDictCreate (void); XMLPUBFUN size_t XMLCALL xmlDictSetLimit (xmlDictPtr dict, size_t limit); XMLPUBFUN size_t XMLCALL xmlDictGetUsage (xmlDictPtr dict); XMLPUBFUN xmlDictPtr XMLCALL xmlDictCreateSub(xmlDictPtr sub); XMLPUBFUN int XMLCALL xmlDictReference(xmlDictPtr dict); XMLPUBFUN void XMLCALL xmlDictFree (xmlDictPtr dict); /* * Lookup of entry in the dictionary. */ XMLPUBFUN const xmlChar * XMLCALL xmlDictLookup (xmlDictPtr dict, const xmlChar *name, int len); XMLPUBFUN const xmlChar * XMLCALL xmlDictExists (xmlDictPtr dict, const xmlChar *name, int len); XMLPUBFUN const xmlChar * XMLCALL xmlDictQLookup (xmlDictPtr dict, const xmlChar *prefix, const xmlChar *name); XMLPUBFUN int XMLCALL xmlDictOwns (xmlDictPtr dict, const xmlChar *str); XMLPUBFUN int XMLCALL xmlDictSize (xmlDictPtr dict); /* * Cleanup function */ XMLPUBFUN void XMLCALL xmlDictCleanup (void); #ifdef __cplusplus } #endif #endif /* ! __XML_DICT_H__ */ PK!ZX2~6565libxml/valid.hnu[/* * Summary: The DTD validation * Description: API for the DTD handling and the validity checking * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_VALID_H__ #define __XML_VALID_H__ #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Validation state added for non-determinist content model. */ typedef struct _xmlValidState xmlValidState; typedef xmlValidState *xmlValidStatePtr; /** * xmlValidityErrorFunc: * @ctx: usually an xmlValidCtxtPtr to a validity error context, * but comes from ctxt->userData (which normally contains such * a pointer); ctxt->userData can be changed by the user. * @msg: the string to format *printf like vararg * @...: remaining arguments to the format * * Callback called when a validity error is found. This is a message * oriented function similar to an *printf function. */ typedef void (XMLCDECL *xmlValidityErrorFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * xmlValidityWarningFunc: * @ctx: usually an xmlValidCtxtPtr to a validity error context, * but comes from ctxt->userData (which normally contains such * a pointer); ctxt->userData can be changed by the user. * @msg: the string to format *printf like vararg * @...: remaining arguments to the format * * Callback called when a validity warning is found. This is a message * oriented function similar to an *printf function. */ typedef void (XMLCDECL *xmlValidityWarningFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); #ifdef IN_LIBXML /** * XML_CTXT_FINISH_DTD_0: * * Special value for finishDtd field when embedded in an xmlParserCtxt */ #define XML_CTXT_FINISH_DTD_0 0xabcd1234 /** * XML_CTXT_FINISH_DTD_1: * * Special value for finishDtd field when embedded in an xmlParserCtxt */ #define XML_CTXT_FINISH_DTD_1 0xabcd1235 #endif /* * xmlValidCtxt: * An xmlValidCtxt is used for error reporting when validating. */ typedef struct _xmlValidCtxt xmlValidCtxt; typedef xmlValidCtxt *xmlValidCtxtPtr; struct _xmlValidCtxt { void *userData; /* user specific data block */ xmlValidityErrorFunc error; /* the callback in case of errors */ xmlValidityWarningFunc warning; /* the callback in case of warning */ /* Node analysis stack used when validating within entities */ xmlNodePtr node; /* Current parsed Node */ int nodeNr; /* Depth of the parsing stack */ int nodeMax; /* Max depth of the parsing stack */ xmlNodePtr *nodeTab; /* array of nodes */ unsigned int finishDtd; /* finished validating the Dtd ? */ xmlDocPtr doc; /* the document */ int valid; /* temporary validity check result */ /* state state used for non-determinist content validation */ xmlValidState *vstate; /* current state */ int vstateNr; /* Depth of the validation stack */ int vstateMax; /* Max depth of the validation stack */ xmlValidState *vstateTab; /* array of validation states */ #ifdef LIBXML_REGEXP_ENABLED xmlAutomataPtr am; /* the automata */ xmlAutomataStatePtr state; /* used to build the automata */ #else void *am; void *state; #endif }; /* * ALL notation declarations are stored in a table. * There is one table per DTD. */ typedef struct _xmlHashTable xmlNotationTable; typedef xmlNotationTable *xmlNotationTablePtr; /* * ALL element declarations are stored in a table. * There is one table per DTD. */ typedef struct _xmlHashTable xmlElementTable; typedef xmlElementTable *xmlElementTablePtr; /* * ALL attribute declarations are stored in a table. * There is one table per DTD. */ typedef struct _xmlHashTable xmlAttributeTable; typedef xmlAttributeTable *xmlAttributeTablePtr; /* * ALL IDs attributes are stored in a table. * There is one table per document. */ typedef struct _xmlHashTable xmlIDTable; typedef xmlIDTable *xmlIDTablePtr; /* * ALL Refs attributes are stored in a table. * There is one table per document. */ typedef struct _xmlHashTable xmlRefTable; typedef xmlRefTable *xmlRefTablePtr; /* Notation */ XMLPUBFUN xmlNotationPtr XMLCALL xmlAddNotationDecl (xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, const xmlChar *PublicID, const xmlChar *SystemID); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlNotationTablePtr XMLCALL xmlCopyNotationTable (xmlNotationTablePtr table); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN void XMLCALL xmlFreeNotationTable (xmlNotationTablePtr table); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlDumpNotationDecl (xmlBufferPtr buf, xmlNotationPtr nota); XMLPUBFUN void XMLCALL xmlDumpNotationTable (xmlBufferPtr buf, xmlNotationTablePtr table); #endif /* LIBXML_OUTPUT_ENABLED */ /* Element Content */ /* the non Doc version are being deprecated */ XMLPUBFUN xmlElementContentPtr XMLCALL xmlNewElementContent (const xmlChar *name, xmlElementContentType type); XMLPUBFUN xmlElementContentPtr XMLCALL xmlCopyElementContent (xmlElementContentPtr content); XMLPUBFUN void XMLCALL xmlFreeElementContent (xmlElementContentPtr cur); /* the new versions with doc argument */ XMLPUBFUN xmlElementContentPtr XMLCALL xmlNewDocElementContent (xmlDocPtr doc, const xmlChar *name, xmlElementContentType type); XMLPUBFUN xmlElementContentPtr XMLCALL xmlCopyDocElementContent(xmlDocPtr doc, xmlElementContentPtr content); XMLPUBFUN void XMLCALL xmlFreeDocElementContent(xmlDocPtr doc, xmlElementContentPtr cur); XMLPUBFUN void XMLCALL xmlSnprintfElementContent(char *buf, int size, xmlElementContentPtr content, int englob); #ifdef LIBXML_OUTPUT_ENABLED /* DEPRECATED */ XMLPUBFUN void XMLCALL xmlSprintfElementContent(char *buf, xmlElementContentPtr content, int englob); #endif /* LIBXML_OUTPUT_ENABLED */ /* DEPRECATED */ /* Element */ XMLPUBFUN xmlElementPtr XMLCALL xmlAddElementDecl (xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *name, xmlElementTypeVal type, xmlElementContentPtr content); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlElementTablePtr XMLCALL xmlCopyElementTable (xmlElementTablePtr table); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN void XMLCALL xmlFreeElementTable (xmlElementTablePtr table); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlDumpElementTable (xmlBufferPtr buf, xmlElementTablePtr table); XMLPUBFUN void XMLCALL xmlDumpElementDecl (xmlBufferPtr buf, xmlElementPtr elem); #endif /* LIBXML_OUTPUT_ENABLED */ /* Enumeration */ XMLPUBFUN xmlEnumerationPtr XMLCALL xmlCreateEnumeration (const xmlChar *name); XMLPUBFUN void XMLCALL xmlFreeEnumeration (xmlEnumerationPtr cur); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlEnumerationPtr XMLCALL xmlCopyEnumeration (xmlEnumerationPtr cur); #endif /* LIBXML_TREE_ENABLED */ /* Attribute */ XMLPUBFUN xmlAttributePtr XMLCALL xmlAddAttributeDecl (xmlValidCtxtPtr ctxt, xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name, const xmlChar *ns, xmlAttributeType type, xmlAttributeDefault def, const xmlChar *defaultValue, xmlEnumerationPtr tree); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlAttributeTablePtr XMLCALL xmlCopyAttributeTable (xmlAttributeTablePtr table); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN void XMLCALL xmlFreeAttributeTable (xmlAttributeTablePtr table); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlDumpAttributeTable (xmlBufferPtr buf, xmlAttributeTablePtr table); XMLPUBFUN void XMLCALL xmlDumpAttributeDecl (xmlBufferPtr buf, xmlAttributePtr attr); #endif /* LIBXML_OUTPUT_ENABLED */ /* IDs */ XMLPUBFUN xmlIDPtr XMLCALL xmlAddID (xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr); XMLPUBFUN void XMLCALL xmlFreeIDTable (xmlIDTablePtr table); XMLPUBFUN xmlAttrPtr XMLCALL xmlGetID (xmlDocPtr doc, const xmlChar *ID); XMLPUBFUN int XMLCALL xmlIsID (xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr); XMLPUBFUN int XMLCALL xmlRemoveID (xmlDocPtr doc, xmlAttrPtr attr); /* IDREFs */ XMLPUBFUN xmlRefPtr XMLCALL xmlAddRef (xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value, xmlAttrPtr attr); XMLPUBFUN void XMLCALL xmlFreeRefTable (xmlRefTablePtr table); XMLPUBFUN int XMLCALL xmlIsRef (xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr); XMLPUBFUN int XMLCALL xmlRemoveRef (xmlDocPtr doc, xmlAttrPtr attr); XMLPUBFUN xmlListPtr XMLCALL xmlGetRefs (xmlDocPtr doc, const xmlChar *ID); /** * The public function calls related to validity checking. */ #ifdef LIBXML_VALID_ENABLED /* Allocate/Release Validation Contexts */ XMLPUBFUN xmlValidCtxtPtr XMLCALL xmlNewValidCtxt(void); XMLPUBFUN void XMLCALL xmlFreeValidCtxt(xmlValidCtxtPtr); XMLPUBFUN int XMLCALL xmlValidateRoot (xmlValidCtxtPtr ctxt, xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlValidateElementDecl (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlElementPtr elem); XMLPUBFUN xmlChar * XMLCALL xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem, const xmlChar *name, const xmlChar *value); XMLPUBFUN xmlChar * XMLCALL xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *name, const xmlChar *value); XMLPUBFUN int XMLCALL xmlValidateAttributeDecl(xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlAttributePtr attr); XMLPUBFUN int XMLCALL xmlValidateAttributeValue(xmlAttributeType type, const xmlChar *value); XMLPUBFUN int XMLCALL xmlValidateNotationDecl (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNotationPtr nota); XMLPUBFUN int XMLCALL xmlValidateDtd (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlDtdPtr dtd); XMLPUBFUN int XMLCALL xmlValidateDtdFinal (xmlValidCtxtPtr ctxt, xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlValidateDocument (xmlValidCtxtPtr ctxt, xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlValidateElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem); XMLPUBFUN int XMLCALL xmlValidateOneElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem); XMLPUBFUN int XMLCALL xmlValidateOneAttribute (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, xmlAttrPtr attr, const xmlChar *value); XMLPUBFUN int XMLCALL xmlValidateOneNamespace (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *prefix, xmlNsPtr ns, const xmlChar *value); XMLPUBFUN int XMLCALL xmlValidateDocumentFinal(xmlValidCtxtPtr ctxt, xmlDocPtr doc); #endif /* LIBXML_VALID_ENABLED */ #if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN int XMLCALL xmlValidateNotationUse (xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *notationName); #endif /* LIBXML_VALID_ENABLED or LIBXML_SCHEMAS_ENABLED */ XMLPUBFUN int XMLCALL xmlIsMixedElement (xmlDocPtr doc, const xmlChar *name); XMLPUBFUN xmlAttributePtr XMLCALL xmlGetDtdAttrDesc (xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name); XMLPUBFUN xmlAttributePtr XMLCALL xmlGetDtdQAttrDesc (xmlDtdPtr dtd, const xmlChar *elem, const xmlChar *name, const xmlChar *prefix); XMLPUBFUN xmlNotationPtr XMLCALL xmlGetDtdNotationDesc (xmlDtdPtr dtd, const xmlChar *name); XMLPUBFUN xmlElementPtr XMLCALL xmlGetDtdQElementDesc (xmlDtdPtr dtd, const xmlChar *name, const xmlChar *prefix); XMLPUBFUN xmlElementPtr XMLCALL xmlGetDtdElementDesc (xmlDtdPtr dtd, const xmlChar *name); #ifdef LIBXML_VALID_ENABLED XMLPUBFUN int XMLCALL xmlValidGetPotentialChildren(xmlElementContent *ctree, const xmlChar **names, int *len, int max); XMLPUBFUN int XMLCALL xmlValidGetValidElements(xmlNode *prev, xmlNode *next, const xmlChar **names, int max); XMLPUBFUN int XMLCALL xmlValidateNameValue (const xmlChar *value); XMLPUBFUN int XMLCALL xmlValidateNamesValue (const xmlChar *value); XMLPUBFUN int XMLCALL xmlValidateNmtokenValue (const xmlChar *value); XMLPUBFUN int XMLCALL xmlValidateNmtokensValue(const xmlChar *value); #ifdef LIBXML_REGEXP_ENABLED /* * Validation based on the regexp support */ XMLPUBFUN int XMLCALL xmlValidBuildContentModel(xmlValidCtxtPtr ctxt, xmlElementPtr elem); XMLPUBFUN int XMLCALL xmlValidatePushElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *qname); XMLPUBFUN int XMLCALL xmlValidatePushCData (xmlValidCtxtPtr ctxt, const xmlChar *data, int len); XMLPUBFUN int XMLCALL xmlValidatePopElement (xmlValidCtxtPtr ctxt, xmlDocPtr doc, xmlNodePtr elem, const xmlChar *qname); #endif /* LIBXML_REGEXP_ENABLED */ #endif /* LIBXML_VALID_ENABLED */ #ifdef __cplusplus } #endif #endif /* __XML_VALID_H__ */ PK!6SSlibxml/xmlwriter.hnu[/* * Summary: text writing API for XML * Description: text writing API for XML * * Copy: See Copyright for the status of this software. * * Author: Alfred Mickautsch */ #ifndef __XML_XMLWRITER_H__ #define __XML_XMLWRITER_H__ #include #ifdef LIBXML_WRITER_ENABLED #include #include #include #include #ifdef __cplusplus extern "C" { #endif typedef struct _xmlTextWriter xmlTextWriter; typedef xmlTextWriter *xmlTextWriterPtr; /* * Constructors & Destructor */ XMLPUBFUN xmlTextWriterPtr XMLCALL xmlNewTextWriter(xmlOutputBufferPtr out); XMLPUBFUN xmlTextWriterPtr XMLCALL xmlNewTextWriterFilename(const char *uri, int compression); XMLPUBFUN xmlTextWriterPtr XMLCALL xmlNewTextWriterMemory(xmlBufferPtr buf, int compression); XMLPUBFUN xmlTextWriterPtr XMLCALL xmlNewTextWriterPushParser(xmlParserCtxtPtr ctxt, int compression); XMLPUBFUN xmlTextWriterPtr XMLCALL xmlNewTextWriterDoc(xmlDocPtr * doc, int compression); XMLPUBFUN xmlTextWriterPtr XMLCALL xmlNewTextWriterTree(xmlDocPtr doc, xmlNodePtr node, int compression); XMLPUBFUN void XMLCALL xmlFreeTextWriter(xmlTextWriterPtr writer); /* * Functions */ /* * Document */ XMLPUBFUN int XMLCALL xmlTextWriterStartDocument(xmlTextWriterPtr writer, const char *version, const char *encoding, const char *standalone); XMLPUBFUN int XMLCALL xmlTextWriterEndDocument(xmlTextWriterPtr writer); /* * Comments */ XMLPUBFUN int XMLCALL xmlTextWriterStartComment(xmlTextWriterPtr writer); XMLPUBFUN int XMLCALL xmlTextWriterEndComment(xmlTextWriterPtr writer); XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatComment(xmlTextWriterPtr writer, const char *format, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatComment(xmlTextWriterPtr writer, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(2,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteComment(xmlTextWriterPtr writer, const xmlChar * content); /* * Elements */ XMLPUBFUN int XMLCALL xmlTextWriterStartElement(xmlTextWriterPtr writer, const xmlChar * name); XMLPUBFUN int XMLCALL xmlTextWriterStartElementNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI); XMLPUBFUN int XMLCALL xmlTextWriterEndElement(xmlTextWriterPtr writer); XMLPUBFUN int XMLCALL xmlTextWriterFullEndElement(xmlTextWriterPtr writer); /* * Elements conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatElement(xmlTextWriterPtr writer, const xmlChar * name, const char *format, ...) LIBXML_ATTR_FORMAT(3,4); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatElement(xmlTextWriterPtr writer, const xmlChar * name, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(3,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteElement(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * content); XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatElementNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI, const char *format, ...) LIBXML_ATTR_FORMAT(5,6); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatElementNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(5,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteElementNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI, const xmlChar * content); /* * Text */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatRaw(xmlTextWriterPtr writer, const char *format, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatRaw(xmlTextWriterPtr writer, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(2,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteRawLen(xmlTextWriterPtr writer, const xmlChar * content, int len); XMLPUBFUN int XMLCALL xmlTextWriterWriteRaw(xmlTextWriterPtr writer, const xmlChar * content); XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatString(xmlTextWriterPtr writer, const char *format, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatString(xmlTextWriterPtr writer, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(2,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteString(xmlTextWriterPtr writer, const xmlChar * content); XMLPUBFUN int XMLCALL xmlTextWriterWriteBase64(xmlTextWriterPtr writer, const char *data, int start, int len); XMLPUBFUN int XMLCALL xmlTextWriterWriteBinHex(xmlTextWriterPtr writer, const char *data, int start, int len); /* * Attributes */ XMLPUBFUN int XMLCALL xmlTextWriterStartAttribute(xmlTextWriterPtr writer, const xmlChar * name); XMLPUBFUN int XMLCALL xmlTextWriterStartAttributeNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI); XMLPUBFUN int XMLCALL xmlTextWriterEndAttribute(xmlTextWriterPtr writer); /* * Attributes conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatAttribute(xmlTextWriterPtr writer, const xmlChar * name, const char *format, ...) LIBXML_ATTR_FORMAT(3,4); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatAttribute(xmlTextWriterPtr writer, const xmlChar * name, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(3,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteAttribute(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * content); XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatAttributeNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI, const char *format, ...) LIBXML_ATTR_FORMAT(5,6); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatAttributeNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(5,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteAttributeNS(xmlTextWriterPtr writer, const xmlChar * prefix, const xmlChar * name, const xmlChar * namespaceURI, const xmlChar * content); /* * PI's */ XMLPUBFUN int XMLCALL xmlTextWriterStartPI(xmlTextWriterPtr writer, const xmlChar * target); XMLPUBFUN int XMLCALL xmlTextWriterEndPI(xmlTextWriterPtr writer); /* * PI conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatPI(xmlTextWriterPtr writer, const xmlChar * target, const char *format, ...) LIBXML_ATTR_FORMAT(3,4); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatPI(xmlTextWriterPtr writer, const xmlChar * target, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(3,0); XMLPUBFUN int XMLCALL xmlTextWriterWritePI(xmlTextWriterPtr writer, const xmlChar * target, const xmlChar * content); /** * xmlTextWriterWriteProcessingInstruction: * * This macro maps to xmlTextWriterWritePI */ #define xmlTextWriterWriteProcessingInstruction xmlTextWriterWritePI /* * CDATA */ XMLPUBFUN int XMLCALL xmlTextWriterStartCDATA(xmlTextWriterPtr writer); XMLPUBFUN int XMLCALL xmlTextWriterEndCDATA(xmlTextWriterPtr writer); /* * CDATA conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatCDATA(xmlTextWriterPtr writer, const char *format, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatCDATA(xmlTextWriterPtr writer, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(2,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteCDATA(xmlTextWriterPtr writer, const xmlChar * content); /* * DTD */ XMLPUBFUN int XMLCALL xmlTextWriterStartDTD(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * pubid, const xmlChar * sysid); XMLPUBFUN int XMLCALL xmlTextWriterEndDTD(xmlTextWriterPtr writer); /* * DTD conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatDTD(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * pubid, const xmlChar * sysid, const char *format, ...) LIBXML_ATTR_FORMAT(5,6); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatDTD(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * pubid, const xmlChar * sysid, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(5,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteDTD(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * pubid, const xmlChar * sysid, const xmlChar * subset); /** * xmlTextWriterWriteDocType: * * this macro maps to xmlTextWriterWriteDTD */ #define xmlTextWriterWriteDocType xmlTextWriterWriteDTD /* * DTD element definition */ XMLPUBFUN int XMLCALL xmlTextWriterStartDTDElement(xmlTextWriterPtr writer, const xmlChar * name); XMLPUBFUN int XMLCALL xmlTextWriterEndDTDElement(xmlTextWriterPtr writer); /* * DTD element definition conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatDTDElement(xmlTextWriterPtr writer, const xmlChar * name, const char *format, ...) LIBXML_ATTR_FORMAT(3,4); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatDTDElement(xmlTextWriterPtr writer, const xmlChar * name, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(3,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDElement(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * content); /* * DTD attribute list definition */ XMLPUBFUN int XMLCALL xmlTextWriterStartDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name); XMLPUBFUN int XMLCALL xmlTextWriterEndDTDAttlist(xmlTextWriterPtr writer); /* * DTD attribute list definition conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name, const char *format, ...) LIBXML_ATTR_FORMAT(3,4); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(3,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDAttlist(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * content); /* * DTD entity definition */ XMLPUBFUN int XMLCALL xmlTextWriterStartDTDEntity(xmlTextWriterPtr writer, int pe, const xmlChar * name); XMLPUBFUN int XMLCALL xmlTextWriterEndDTDEntity(xmlTextWriterPtr writer); /* * DTD entity definition conveniency functions */ XMLPUBFUN int XMLCALL xmlTextWriterWriteFormatDTDInternalEntity(xmlTextWriterPtr writer, int pe, const xmlChar * name, const char *format, ...) LIBXML_ATTR_FORMAT(4,5); XMLPUBFUN int XMLCALL xmlTextWriterWriteVFormatDTDInternalEntity(xmlTextWriterPtr writer, int pe, const xmlChar * name, const char *format, va_list argptr) LIBXML_ATTR_FORMAT(4,0); XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDInternalEntity(xmlTextWriterPtr writer, int pe, const xmlChar * name, const xmlChar * content); XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDExternalEntity(xmlTextWriterPtr writer, int pe, const xmlChar * name, const xmlChar * pubid, const xmlChar * sysid, const xmlChar * ndataid); XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDExternalEntityContents(xmlTextWriterPtr writer, const xmlChar * pubid, const xmlChar * sysid, const xmlChar * ndataid); XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDEntity(xmlTextWriterPtr writer, int pe, const xmlChar * name, const xmlChar * pubid, const xmlChar * sysid, const xmlChar * ndataid, const xmlChar * content); /* * DTD notation definition */ XMLPUBFUN int XMLCALL xmlTextWriterWriteDTDNotation(xmlTextWriterPtr writer, const xmlChar * name, const xmlChar * pubid, const xmlChar * sysid); /* * Indentation */ XMLPUBFUN int XMLCALL xmlTextWriterSetIndent(xmlTextWriterPtr writer, int indent); XMLPUBFUN int XMLCALL xmlTextWriterSetIndentString(xmlTextWriterPtr writer, const xmlChar * str); XMLPUBFUN int XMLCALL xmlTextWriterSetQuoteChar(xmlTextWriterPtr writer, xmlChar quotechar); /* * misc */ XMLPUBFUN int XMLCALL xmlTextWriterFlush(xmlTextWriterPtr writer); #ifdef __cplusplus } #endif #endif /* LIBXML_WRITER_ENABLED */ #endif /* __XML_XMLWRITER_H__ */ PK!U& D Dlibxml/parserInternals.hnu[/* * Summary: internals routines and limits exported by the parser. * Description: this module exports a number of internal parsing routines * they are not really all intended for applications but * can prove useful doing low level processing. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_PARSER_INTERNALS_H__ #define __XML_PARSER_INTERNALS_H__ #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * xmlParserMaxDepth: * * arbitrary depth limit for the XML documents that we allow to * process. This is not a limitation of the parser but a safety * boundary feature, use XML_PARSE_HUGE option to override it. */ XMLPUBVAR unsigned int xmlParserMaxDepth; /** * XML_MAX_TEXT_LENGTH: * * Maximum size allowed for a single text node when building a tree. * This is not a limitation of the parser but a safety boundary feature, * use XML_PARSE_HUGE option to override it. * Introduced in 2.9.0 */ #define XML_MAX_TEXT_LENGTH 10000000 /** * XML_MAX_NAME_LENGTH: * * Maximum size allowed for a markup identifier. * This is not a limitation of the parser but a safety boundary feature, * use XML_PARSE_HUGE option to override it. * Note that with the use of parsing dictionaries overriding the limit * may result in more runtime memory usage in face of "unfriendly' content * Introduced in 2.9.0 */ #define XML_MAX_NAME_LENGTH 50000 /** * XML_MAX_DICTIONARY_LIMIT: * * Maximum size allowed by the parser for a dictionary by default * This is not a limitation of the parser but a safety boundary feature, * use XML_PARSE_HUGE option to override it. * Introduced in 2.9.0 */ #define XML_MAX_DICTIONARY_LIMIT 10000000 /** * XML_MAX_LOOKUP_LIMIT: * * Maximum size allowed by the parser for ahead lookup * This is an upper boundary enforced by the parser to avoid bad * behaviour on "unfriendly' content * Introduced in 2.9.0 */ #define XML_MAX_LOOKUP_LIMIT 10000000 /** * XML_MAX_NAMELEN: * * Identifiers can be longer, but this will be more costly * at runtime. */ #define XML_MAX_NAMELEN 100 /** * INPUT_CHUNK: * * The parser tries to always have that amount of input ready. * One of the point is providing context when reporting errors. */ #define INPUT_CHUNK 250 /************************************************************************ * * * UNICODE version of the macros. * * * ************************************************************************/ /** * IS_BYTE_CHAR: * @c: an byte value (int) * * Macro to check the following production in the XML spec: * * [2] Char ::= #x9 | #xA | #xD | [#x20...] * any byte character in the accepted range */ #define IS_BYTE_CHAR(c) xmlIsChar_ch(c) /** * IS_CHAR: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] * | [#x10000-#x10FFFF] * any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */ #define IS_CHAR(c) xmlIsCharQ(c) /** * IS_CHAR_CH: * @c: an xmlChar (usually an unsigned char) * * Behaves like IS_CHAR on single-byte value */ #define IS_CHAR_CH(c) xmlIsChar_ch(c) /** * IS_BLANK: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * [3] S ::= (#x20 | #x9 | #xD | #xA)+ */ #define IS_BLANK(c) xmlIsBlankQ(c) /** * IS_BLANK_CH: * @c: an xmlChar value (normally unsigned char) * * Behaviour same as IS_BLANK */ #define IS_BLANK_CH(c) xmlIsBlank_ch(c) /** * IS_BASECHAR: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * [85] BaseChar ::= ... long list see REC ... */ #define IS_BASECHAR(c) xmlIsBaseCharQ(c) /** * IS_DIGIT: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * [88] Digit ::= ... long list see REC ... */ #define IS_DIGIT(c) xmlIsDigitQ(c) /** * IS_DIGIT_CH: * @c: an xmlChar value (usually an unsigned char) * * Behaves like IS_DIGIT but with a single byte argument */ #define IS_DIGIT_CH(c) xmlIsDigit_ch(c) /** * IS_COMBINING: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * [87] CombiningChar ::= ... long list see REC ... */ #define IS_COMBINING(c) xmlIsCombiningQ(c) /** * IS_COMBINING_CH: * @c: an xmlChar (usually an unsigned char) * * Always false (all combining chars > 0xff) */ #define IS_COMBINING_CH(c) 0 /** * IS_EXTENDER: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * * [89] Extender ::= #x00B7 | #x02D0 | #x02D1 | #x0387 | #x0640 | * #x0E46 | #x0EC6 | #x3005 | [#x3031-#x3035] | * [#x309D-#x309E] | [#x30FC-#x30FE] */ #define IS_EXTENDER(c) xmlIsExtenderQ(c) /** * IS_EXTENDER_CH: * @c: an xmlChar value (usually an unsigned char) * * Behaves like IS_EXTENDER but with a single-byte argument */ #define IS_EXTENDER_CH(c) xmlIsExtender_ch(c) /** * IS_IDEOGRAPHIC: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * * [86] Ideographic ::= [#x4E00-#x9FA5] | #x3007 | [#x3021-#x3029] */ #define IS_IDEOGRAPHIC(c) xmlIsIdeographicQ(c) /** * IS_LETTER: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * * [84] Letter ::= BaseChar | Ideographic */ #define IS_LETTER(c) (IS_BASECHAR(c) || IS_IDEOGRAPHIC(c)) /** * IS_LETTER_CH: * @c: an xmlChar value (normally unsigned char) * * Macro behaves like IS_LETTER, but only check base chars * */ #define IS_LETTER_CH(c) xmlIsBaseChar_ch(c) /** * IS_ASCII_LETTER: * @c: an xmlChar value * * Macro to check [a-zA-Z] * */ #define IS_ASCII_LETTER(c) (((0x41 <= (c)) && ((c) <= 0x5a)) || \ ((0x61 <= (c)) && ((c) <= 0x7a))) /** * IS_ASCII_DIGIT: * @c: an xmlChar value * * Macro to check [0-9] * */ #define IS_ASCII_DIGIT(c) ((0x30 <= (c)) && ((c) <= 0x39)) /** * IS_PUBIDCHAR: * @c: an UNICODE value (int) * * Macro to check the following production in the XML spec: * * * [13] PubidChar ::= #x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%] */ #define IS_PUBIDCHAR(c) xmlIsPubidCharQ(c) /** * IS_PUBIDCHAR_CH: * @c: an xmlChar value (normally unsigned char) * * Same as IS_PUBIDCHAR but for single-byte value */ #define IS_PUBIDCHAR_CH(c) xmlIsPubidChar_ch(c) /** * SKIP_EOL: * @p: and UTF8 string pointer * * Skips the end of line chars. */ #define SKIP_EOL(p) \ if (*(p) == 0x13) { p++ ; if (*(p) == 0x10) p++; } \ if (*(p) == 0x10) { p++ ; if (*(p) == 0x13) p++; } /** * MOVETO_ENDTAG: * @p: and UTF8 string pointer * * Skips to the next '>' char. */ #define MOVETO_ENDTAG(p) \ while ((*p) && (*(p) != '>')) (p)++ /** * MOVETO_STARTTAG: * @p: and UTF8 string pointer * * Skips to the next '<' char. */ #define MOVETO_STARTTAG(p) \ while ((*p) && (*(p) != '<')) (p)++ /** * Global variables used for predefined strings. */ XMLPUBVAR const xmlChar xmlStringText[]; XMLPUBVAR const xmlChar xmlStringTextNoenc[]; XMLPUBVAR const xmlChar xmlStringComment[]; /* * Function to finish the work of the macros where needed. */ XMLPUBFUN int XMLCALL xmlIsLetter (int c); /** * Parser context. */ XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlCreateFileParserCtxt (const char *filename); XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlCreateURLParserCtxt (const char *filename, int options); XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlCreateMemoryParserCtxt(const char *buffer, int size); XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlCreateEntityParserCtxt(const xmlChar *URL, const xmlChar *ID, const xmlChar *base); XMLPUBFUN int XMLCALL xmlSwitchEncoding (xmlParserCtxtPtr ctxt, xmlCharEncoding enc); XMLPUBFUN int XMLCALL xmlSwitchToEncoding (xmlParserCtxtPtr ctxt, xmlCharEncodingHandlerPtr handler); XMLPUBFUN int XMLCALL xmlSwitchInputEncoding (xmlParserCtxtPtr ctxt, xmlParserInputPtr input, xmlCharEncodingHandlerPtr handler); #ifdef IN_LIBXML /* internal error reporting */ XMLPUBFUN void XMLCALL __xmlErrEncoding (xmlParserCtxtPtr ctxt, xmlParserErrors xmlerr, const char *msg, const xmlChar * str1, const xmlChar * str2) LIBXML_ATTR_FORMAT(3,0); #endif /** * Input Streams. */ XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewStringInputStream (xmlParserCtxtPtr ctxt, const xmlChar *buffer); XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewEntityInputStream (xmlParserCtxtPtr ctxt, xmlEntityPtr entity); XMLPUBFUN int XMLCALL xmlPushInput (xmlParserCtxtPtr ctxt, xmlParserInputPtr input); XMLPUBFUN xmlChar XMLCALL xmlPopInput (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlFreeInputStream (xmlParserInputPtr input); XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewInputFromFile (xmlParserCtxtPtr ctxt, const char *filename); XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewInputStream (xmlParserCtxtPtr ctxt); /** * Namespaces. */ XMLPUBFUN xmlChar * XMLCALL xmlSplitQName (xmlParserCtxtPtr ctxt, const xmlChar *name, xmlChar **prefix); /** * Generic production rules. */ XMLPUBFUN const xmlChar * XMLCALL xmlParseName (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlParseNmtoken (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlParseEntityValue (xmlParserCtxtPtr ctxt, xmlChar **orig); XMLPUBFUN xmlChar * XMLCALL xmlParseAttValue (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlParseSystemLiteral (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlParsePubidLiteral (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseCharData (xmlParserCtxtPtr ctxt, int cdata); XMLPUBFUN xmlChar * XMLCALL xmlParseExternalID (xmlParserCtxtPtr ctxt, xmlChar **publicID, int strict); XMLPUBFUN void XMLCALL xmlParseComment (xmlParserCtxtPtr ctxt); XMLPUBFUN const xmlChar * XMLCALL xmlParsePITarget (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParsePI (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseNotationDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseEntityDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlParseDefaultDecl (xmlParserCtxtPtr ctxt, xmlChar **value); XMLPUBFUN xmlEnumerationPtr XMLCALL xmlParseNotationType (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlEnumerationPtr XMLCALL xmlParseEnumerationType (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlParseEnumeratedType (xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree); XMLPUBFUN int XMLCALL xmlParseAttributeType (xmlParserCtxtPtr ctxt, xmlEnumerationPtr *tree); XMLPUBFUN void XMLCALL xmlParseAttributeListDecl(xmlParserCtxtPtr ctxt); XMLPUBFUN xmlElementContentPtr XMLCALL xmlParseElementMixedContentDecl (xmlParserCtxtPtr ctxt, int inputchk); XMLPUBFUN xmlElementContentPtr XMLCALL xmlParseElementChildrenContentDecl (xmlParserCtxtPtr ctxt, int inputchk); XMLPUBFUN int XMLCALL xmlParseElementContentDecl(xmlParserCtxtPtr ctxt, const xmlChar *name, xmlElementContentPtr *result); XMLPUBFUN int XMLCALL xmlParseElementDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseMarkupDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlParseCharRef (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlEntityPtr XMLCALL xmlParseEntityRef (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseReference (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParsePEReference (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseDocTypeDecl (xmlParserCtxtPtr ctxt); #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN const xmlChar * XMLCALL xmlParseAttribute (xmlParserCtxtPtr ctxt, xmlChar **value); XMLPUBFUN const xmlChar * XMLCALL xmlParseStartTag (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseEndTag (xmlParserCtxtPtr ctxt); #endif /* LIBXML_SAX1_ENABLED */ XMLPUBFUN void XMLCALL xmlParseCDSect (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseContent (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseElement (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlParseVersionNum (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlParseVersionInfo (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlParseEncName (xmlParserCtxtPtr ctxt); XMLPUBFUN const xmlChar * XMLCALL xmlParseEncodingDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlParseSDDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseXMLDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseTextDecl (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseMisc (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseExternalSubset (xmlParserCtxtPtr ctxt, const xmlChar *ExternalID, const xmlChar *SystemID); /** * XML_SUBSTITUTE_NONE: * * If no entities need to be substituted. */ #define XML_SUBSTITUTE_NONE 0 /** * XML_SUBSTITUTE_REF: * * Whether general entities need to be substituted. */ #define XML_SUBSTITUTE_REF 1 /** * XML_SUBSTITUTE_PEREF: * * Whether parameter entities need to be substituted. */ #define XML_SUBSTITUTE_PEREF 2 /** * XML_SUBSTITUTE_BOTH: * * Both general and parameter entities need to be substituted. */ #define XML_SUBSTITUTE_BOTH 3 XMLPUBFUN xmlChar * XMLCALL xmlStringDecodeEntities (xmlParserCtxtPtr ctxt, const xmlChar *str, int what, xmlChar end, xmlChar end2, xmlChar end3); XMLPUBFUN xmlChar * XMLCALL xmlStringLenDecodeEntities (xmlParserCtxtPtr ctxt, const xmlChar *str, int len, int what, xmlChar end, xmlChar end2, xmlChar end3); /* * Generated by MACROS on top of parser.c c.f. PUSH_AND_POP. */ XMLPUBFUN int XMLCALL nodePush (xmlParserCtxtPtr ctxt, xmlNodePtr value); XMLPUBFUN xmlNodePtr XMLCALL nodePop (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL inputPush (xmlParserCtxtPtr ctxt, xmlParserInputPtr value); XMLPUBFUN xmlParserInputPtr XMLCALL inputPop (xmlParserCtxtPtr ctxt); XMLPUBFUN const xmlChar * XMLCALL namePop (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL namePush (xmlParserCtxtPtr ctxt, const xmlChar *value); /* * other commodities shared between parser.c and parserInternals. */ XMLPUBFUN int XMLCALL xmlSkipBlankChars (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlStringCurrentChar (xmlParserCtxtPtr ctxt, const xmlChar *cur, int *len); XMLPUBFUN void XMLCALL xmlParserHandlePEReference(xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlCheckLanguageID (const xmlChar *lang); /* * Really core function shared with HTML parser. */ XMLPUBFUN int XMLCALL xmlCurrentChar (xmlParserCtxtPtr ctxt, int *len); XMLPUBFUN int XMLCALL xmlCopyCharMultiByte (xmlChar *out, int val); XMLPUBFUN int XMLCALL xmlCopyChar (int len, xmlChar *out, int val); XMLPUBFUN void XMLCALL xmlNextChar (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParserInputShrink (xmlParserInputPtr in); #ifdef LIBXML_HTML_ENABLED /* * Actually comes from the HTML parser but launched from the init stuff. */ XMLPUBFUN void XMLCALL htmlInitAutoClose (void); XMLPUBFUN htmlParserCtxtPtr XMLCALL htmlCreateFileParserCtxt(const char *filename, const char *encoding); #endif /* * Specific function to keep track of entities references * and used by the XSLT debugger. */ #ifdef LIBXML_LEGACY_ENABLED /** * xmlEntityReferenceFunc: * @ent: the entity * @firstNode: the fist node in the chunk * @lastNode: the last nod in the chunk * * Callback function used when one needs to be able to track back the * provenance of a chunk of nodes inherited from an entity replacement. */ typedef void (*xmlEntityReferenceFunc) (xmlEntityPtr ent, xmlNodePtr firstNode, xmlNodePtr lastNode); XMLPUBFUN void XMLCALL xmlSetEntityReferenceFunc (xmlEntityReferenceFunc func); XMLPUBFUN xmlChar * XMLCALL xmlParseQuotedString (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParseNamespace (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlNamespaceParseNSDef (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlScanName (xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlNamespaceParseNCName (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlParserHandleReference(xmlParserCtxtPtr ctxt); XMLPUBFUN xmlChar * XMLCALL xmlNamespaceParseQName (xmlParserCtxtPtr ctxt, xmlChar **prefix); /** * Entities */ XMLPUBFUN xmlChar * XMLCALL xmlDecodeEntities (xmlParserCtxtPtr ctxt, int len, int what, xmlChar end, xmlChar end2, xmlChar end3); XMLPUBFUN void XMLCALL xmlHandleEntity (xmlParserCtxtPtr ctxt, xmlEntityPtr entity); #endif /* LIBXML_LEGACY_ENABLED */ #ifdef IN_LIBXML /* * internal only */ XMLPUBFUN void XMLCALL xmlErrMemory (xmlParserCtxtPtr ctxt, const char *extra); #endif #ifdef __cplusplus } #endif #endif /* __XML_PARSER_INTERNALS_H__ */ PK!, ?1?1libxml/xmlreader.hnu[/* * Summary: the XMLReader implementation * Description: API of the XML streaming API based on C# interfaces. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XMLREADER_H__ #define __XML_XMLREADER_H__ #include #include #include #ifdef LIBXML_SCHEMAS_ENABLED #include #include #endif #ifdef __cplusplus extern "C" { #endif /** * xmlParserSeverities: * * How severe an error callback is when the per-reader error callback API * is used. */ typedef enum { XML_PARSER_SEVERITY_VALIDITY_WARNING = 1, XML_PARSER_SEVERITY_VALIDITY_ERROR = 2, XML_PARSER_SEVERITY_WARNING = 3, XML_PARSER_SEVERITY_ERROR = 4 } xmlParserSeverities; #ifdef LIBXML_READER_ENABLED /** * xmlTextReaderMode: * * Internal state values for the reader. */ typedef enum { XML_TEXTREADER_MODE_INITIAL = 0, XML_TEXTREADER_MODE_INTERACTIVE = 1, XML_TEXTREADER_MODE_ERROR = 2, XML_TEXTREADER_MODE_EOF =3, XML_TEXTREADER_MODE_CLOSED = 4, XML_TEXTREADER_MODE_READING = 5 } xmlTextReaderMode; /** * xmlParserProperties: * * Some common options to use with xmlTextReaderSetParserProp, but it * is better to use xmlParserOption and the xmlReaderNewxxx and * xmlReaderForxxx APIs now. */ typedef enum { XML_PARSER_LOADDTD = 1, XML_PARSER_DEFAULTATTRS = 2, XML_PARSER_VALIDATE = 3, XML_PARSER_SUBST_ENTITIES = 4 } xmlParserProperties; /** * xmlReaderTypes: * * Predefined constants for the different types of nodes. */ typedef enum { XML_READER_TYPE_NONE = 0, XML_READER_TYPE_ELEMENT = 1, XML_READER_TYPE_ATTRIBUTE = 2, XML_READER_TYPE_TEXT = 3, XML_READER_TYPE_CDATA = 4, XML_READER_TYPE_ENTITY_REFERENCE = 5, XML_READER_TYPE_ENTITY = 6, XML_READER_TYPE_PROCESSING_INSTRUCTION = 7, XML_READER_TYPE_COMMENT = 8, XML_READER_TYPE_DOCUMENT = 9, XML_READER_TYPE_DOCUMENT_TYPE = 10, XML_READER_TYPE_DOCUMENT_FRAGMENT = 11, XML_READER_TYPE_NOTATION = 12, XML_READER_TYPE_WHITESPACE = 13, XML_READER_TYPE_SIGNIFICANT_WHITESPACE = 14, XML_READER_TYPE_END_ELEMENT = 15, XML_READER_TYPE_END_ENTITY = 16, XML_READER_TYPE_XML_DECLARATION = 17 } xmlReaderTypes; /** * xmlTextReader: * * Structure for an xmlReader context. */ typedef struct _xmlTextReader xmlTextReader; /** * xmlTextReaderPtr: * * Pointer to an xmlReader context. */ typedef xmlTextReader *xmlTextReaderPtr; /* * Constructors & Destructor */ XMLPUBFUN xmlTextReaderPtr XMLCALL xmlNewTextReader (xmlParserInputBufferPtr input, const char *URI); XMLPUBFUN xmlTextReaderPtr XMLCALL xmlNewTextReaderFilename(const char *URI); XMLPUBFUN void XMLCALL xmlFreeTextReader (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderSetup(xmlTextReaderPtr reader, xmlParserInputBufferPtr input, const char *URL, const char *encoding, int options); /* * Iterators */ XMLPUBFUN int XMLCALL xmlTextReaderRead (xmlTextReaderPtr reader); #ifdef LIBXML_WRITER_ENABLED XMLPUBFUN xmlChar * XMLCALL xmlTextReaderReadInnerXml(xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderReadOuterXml(xmlTextReaderPtr reader); #endif XMLPUBFUN xmlChar * XMLCALL xmlTextReaderReadString (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderReadAttributeValue(xmlTextReaderPtr reader); /* * Attributes of the node */ XMLPUBFUN int XMLCALL xmlTextReaderAttributeCount(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderDepth (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderHasAttributes(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderHasValue(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderIsDefault (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderIsEmptyElement(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderNodeType (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderQuoteChar (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderReadState (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderIsNamespaceDecl(xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstBaseUri (xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstLocalName (xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstName (xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstNamespaceUri(xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstPrefix (xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstXmlLang (xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstString (xmlTextReaderPtr reader, const xmlChar *str); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstValue (xmlTextReaderPtr reader); /* * use the Const version of the routine for * better performance and simpler code */ XMLPUBFUN xmlChar * XMLCALL xmlTextReaderBaseUri (xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderLocalName (xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderName (xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderNamespaceUri(xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderPrefix (xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderXmlLang (xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderValue (xmlTextReaderPtr reader); /* * Methods of the XmlTextReader */ XMLPUBFUN int XMLCALL xmlTextReaderClose (xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderGetAttributeNo (xmlTextReaderPtr reader, int no); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderGetAttribute (xmlTextReaderPtr reader, const xmlChar *name); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderGetAttributeNs (xmlTextReaderPtr reader, const xmlChar *localName, const xmlChar *namespaceURI); XMLPUBFUN xmlParserInputBufferPtr XMLCALL xmlTextReaderGetRemainder (xmlTextReaderPtr reader); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderLookupNamespace(xmlTextReaderPtr reader, const xmlChar *prefix); XMLPUBFUN int XMLCALL xmlTextReaderMoveToAttributeNo(xmlTextReaderPtr reader, int no); XMLPUBFUN int XMLCALL xmlTextReaderMoveToAttribute(xmlTextReaderPtr reader, const xmlChar *name); XMLPUBFUN int XMLCALL xmlTextReaderMoveToAttributeNs(xmlTextReaderPtr reader, const xmlChar *localName, const xmlChar *namespaceURI); XMLPUBFUN int XMLCALL xmlTextReaderMoveToFirstAttribute(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderMoveToNextAttribute(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderMoveToElement (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderNormalization (xmlTextReaderPtr reader); XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstEncoding (xmlTextReaderPtr reader); /* * Extensions */ XMLPUBFUN int XMLCALL xmlTextReaderSetParserProp (xmlTextReaderPtr reader, int prop, int value); XMLPUBFUN int XMLCALL xmlTextReaderGetParserProp (xmlTextReaderPtr reader, int prop); XMLPUBFUN xmlNodePtr XMLCALL xmlTextReaderCurrentNode (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderGetParserLineNumber(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderGetParserColumnNumber(xmlTextReaderPtr reader); XMLPUBFUN xmlNodePtr XMLCALL xmlTextReaderPreserve (xmlTextReaderPtr reader); #ifdef LIBXML_PATTERN_ENABLED XMLPUBFUN int XMLCALL xmlTextReaderPreservePattern(xmlTextReaderPtr reader, const xmlChar *pattern, const xmlChar **namespaces); #endif /* LIBXML_PATTERN_ENABLED */ XMLPUBFUN xmlDocPtr XMLCALL xmlTextReaderCurrentDoc (xmlTextReaderPtr reader); XMLPUBFUN xmlNodePtr XMLCALL xmlTextReaderExpand (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderNext (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderNextSibling (xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderIsValid (xmlTextReaderPtr reader); #ifdef LIBXML_SCHEMAS_ENABLED XMLPUBFUN int XMLCALL xmlTextReaderRelaxNGValidate(xmlTextReaderPtr reader, const char *rng); XMLPUBFUN int XMLCALL xmlTextReaderRelaxNGValidateCtxt(xmlTextReaderPtr reader, xmlRelaxNGValidCtxtPtr ctxt, int options); XMLPUBFUN int XMLCALL xmlTextReaderRelaxNGSetSchema(xmlTextReaderPtr reader, xmlRelaxNGPtr schema); XMLPUBFUN int XMLCALL xmlTextReaderSchemaValidate (xmlTextReaderPtr reader, const char *xsd); XMLPUBFUN int XMLCALL xmlTextReaderSchemaValidateCtxt(xmlTextReaderPtr reader, xmlSchemaValidCtxtPtr ctxt, int options); XMLPUBFUN int XMLCALL xmlTextReaderSetSchema (xmlTextReaderPtr reader, xmlSchemaPtr schema); #endif XMLPUBFUN const xmlChar * XMLCALL xmlTextReaderConstXmlVersion(xmlTextReaderPtr reader); XMLPUBFUN int XMLCALL xmlTextReaderStandalone (xmlTextReaderPtr reader); /* * Index lookup */ XMLPUBFUN long XMLCALL xmlTextReaderByteConsumed (xmlTextReaderPtr reader); /* * New more complete APIs for simpler creation and reuse of readers */ XMLPUBFUN xmlTextReaderPtr XMLCALL xmlReaderWalker (xmlDocPtr doc); XMLPUBFUN xmlTextReaderPtr XMLCALL xmlReaderForDoc (const xmlChar * cur, const char *URL, const char *encoding, int options); XMLPUBFUN xmlTextReaderPtr XMLCALL xmlReaderForFile (const char *filename, const char *encoding, int options); XMLPUBFUN xmlTextReaderPtr XMLCALL xmlReaderForMemory (const char *buffer, int size, const char *URL, const char *encoding, int options); XMLPUBFUN xmlTextReaderPtr XMLCALL xmlReaderForFd (int fd, const char *URL, const char *encoding, int options); XMLPUBFUN xmlTextReaderPtr XMLCALL xmlReaderForIO (xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options); XMLPUBFUN int XMLCALL xmlReaderNewWalker (xmlTextReaderPtr reader, xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlReaderNewDoc (xmlTextReaderPtr reader, const xmlChar * cur, const char *URL, const char *encoding, int options); XMLPUBFUN int XMLCALL xmlReaderNewFile (xmlTextReaderPtr reader, const char *filename, const char *encoding, int options); XMLPUBFUN int XMLCALL xmlReaderNewMemory (xmlTextReaderPtr reader, const char *buffer, int size, const char *URL, const char *encoding, int options); XMLPUBFUN int XMLCALL xmlReaderNewFd (xmlTextReaderPtr reader, int fd, const char *URL, const char *encoding, int options); XMLPUBFUN int XMLCALL xmlReaderNewIO (xmlTextReaderPtr reader, xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options); /* * Error handling extensions */ typedef void * xmlTextReaderLocatorPtr; /** * xmlTextReaderErrorFunc: * @arg: the user argument * @msg: the message * @severity: the severity of the error * @locator: a locator indicating where the error occurred * * Signature of an error callback from a reader parser */ typedef void (XMLCALL *xmlTextReaderErrorFunc)(void *arg, const char *msg, xmlParserSeverities severity, xmlTextReaderLocatorPtr locator); XMLPUBFUN int XMLCALL xmlTextReaderLocatorLineNumber(xmlTextReaderLocatorPtr locator); XMLPUBFUN xmlChar * XMLCALL xmlTextReaderLocatorBaseURI (xmlTextReaderLocatorPtr locator); XMLPUBFUN void XMLCALL xmlTextReaderSetErrorHandler(xmlTextReaderPtr reader, xmlTextReaderErrorFunc f, void *arg); XMLPUBFUN void XMLCALL xmlTextReaderSetStructuredErrorHandler(xmlTextReaderPtr reader, xmlStructuredErrorFunc f, void *arg); XMLPUBFUN void XMLCALL xmlTextReaderGetErrorHandler(xmlTextReaderPtr reader, xmlTextReaderErrorFunc *f, void **arg); #endif /* LIBXML_READER_ENABLED */ #ifdef __cplusplus } #endif #endif /* __XML_XMLREADER_H__ */ PK!䥽;;libxml/xmlexports.hnu[/* * Summary: macros for marking symbols as exportable/importable. * Description: macros for marking symbols as exportable/importable. * * Copy: See Copyright for the status of this software. */ #ifndef __XML_EXPORTS_H__ #define __XML_EXPORTS_H__ #if defined(_WIN32) || defined(__CYGWIN__) /** DOC_DISABLE */ #ifdef LIBXML_STATIC #define XMLPUBLIC #elif defined(IN_LIBXML) #define XMLPUBLIC __declspec(dllexport) #else #define XMLPUBLIC __declspec(dllimport) #endif #if defined(LIBXML_FASTCALL) #define XMLCALL __fastcall #else #define XMLCALL __cdecl #endif #define XMLCDECL __cdecl /** DOC_ENABLE */ #else /* not Windows */ /** * XMLPUBLIC: * * Macro which declares a public symbol */ #define XMLPUBLIC /** * XMLCALL: * * Macro which declares the calling convention for exported functions */ #define XMLCALL /** * XMLCDECL: * * Macro which declares the calling convention for exported functions that * use '...'. */ #define XMLCDECL #endif /* platform switch */ /* * XMLPUBFUN: * * Macro which declares an exportable function */ #define XMLPUBFUN XMLPUBLIC /** * XMLPUBVAR: * * Macro which declares an exportable variable */ #define XMLPUBVAR XMLPUBLIC extern /* Compatibility */ #if !defined(LIBXML_DLL_IMPORT) #define LIBXML_DLL_IMPORT XMLPUBVAR #endif #endif /* __XML_EXPORTS_H__ */ PK!TI''libxml/chvalid.hnu[/* * Summary: Unicode character range checking * Description: this module exports interfaces for the character * range validation APIs * * This file is automatically generated from the cvs source * definition files using the genChRanges.py Python script * * Generation date: Mon Mar 27 11:09:48 2006 * Sources: chvalid.def * Author: William Brack */ #ifndef __XML_CHVALID_H__ #define __XML_CHVALID_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* * Define our typedefs and structures * */ typedef struct _xmlChSRange xmlChSRange; typedef xmlChSRange *xmlChSRangePtr; struct _xmlChSRange { unsigned short low; unsigned short high; }; typedef struct _xmlChLRange xmlChLRange; typedef xmlChLRange *xmlChLRangePtr; struct _xmlChLRange { unsigned int low; unsigned int high; }; typedef struct _xmlChRangeGroup xmlChRangeGroup; typedef xmlChRangeGroup *xmlChRangeGroupPtr; struct _xmlChRangeGroup { int nbShortRange; int nbLongRange; const xmlChSRange *shortRange; /* points to an array of ranges */ const xmlChLRange *longRange; }; /** * Range checking routine */ XMLPUBFUN int XMLCALL xmlCharInRange(unsigned int val, const xmlChRangeGroup *group); /** * xmlIsBaseChar_ch: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsBaseChar_ch(c) (((0x41 <= (c)) && ((c) <= 0x5a)) || \ ((0x61 <= (c)) && ((c) <= 0x7a)) || \ ((0xc0 <= (c)) && ((c) <= 0xd6)) || \ ((0xd8 <= (c)) && ((c) <= 0xf6)) || \ (0xf8 <= (c))) /** * xmlIsBaseCharQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsBaseCharQ(c) (((c) < 0x100) ? \ xmlIsBaseChar_ch((c)) : \ xmlCharInRange((c), &xmlIsBaseCharGroup)) XMLPUBVAR const xmlChRangeGroup xmlIsBaseCharGroup; /** * xmlIsBlank_ch: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsBlank_ch(c) (((c) == 0x20) || \ ((0x9 <= (c)) && ((c) <= 0xa)) || \ ((c) == 0xd)) /** * xmlIsBlankQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsBlankQ(c) (((c) < 0x100) ? \ xmlIsBlank_ch((c)) : 0) /** * xmlIsChar_ch: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsChar_ch(c) (((0x9 <= (c)) && ((c) <= 0xa)) || \ ((c) == 0xd) || \ (0x20 <= (c))) /** * xmlIsCharQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsCharQ(c) (((c) < 0x100) ? \ xmlIsChar_ch((c)) :\ (((0x100 <= (c)) && ((c) <= 0xd7ff)) || \ ((0xe000 <= (c)) && ((c) <= 0xfffd)) || \ ((0x10000 <= (c)) && ((c) <= 0x10ffff)))) XMLPUBVAR const xmlChRangeGroup xmlIsCharGroup; /** * xmlIsCombiningQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsCombiningQ(c) (((c) < 0x100) ? \ 0 : \ xmlCharInRange((c), &xmlIsCombiningGroup)) XMLPUBVAR const xmlChRangeGroup xmlIsCombiningGroup; /** * xmlIsDigit_ch: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsDigit_ch(c) (((0x30 <= (c)) && ((c) <= 0x39))) /** * xmlIsDigitQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsDigitQ(c) (((c) < 0x100) ? \ xmlIsDigit_ch((c)) : \ xmlCharInRange((c), &xmlIsDigitGroup)) XMLPUBVAR const xmlChRangeGroup xmlIsDigitGroup; /** * xmlIsExtender_ch: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsExtender_ch(c) (((c) == 0xb7)) /** * xmlIsExtenderQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsExtenderQ(c) (((c) < 0x100) ? \ xmlIsExtender_ch((c)) : \ xmlCharInRange((c), &xmlIsExtenderGroup)) XMLPUBVAR const xmlChRangeGroup xmlIsExtenderGroup; /** * xmlIsIdeographicQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsIdeographicQ(c) (((c) < 0x100) ? \ 0 :\ (((0x4e00 <= (c)) && ((c) <= 0x9fa5)) || \ ((c) == 0x3007) || \ ((0x3021 <= (c)) && ((c) <= 0x3029)))) XMLPUBVAR const xmlChRangeGroup xmlIsIdeographicGroup; XMLPUBVAR const unsigned char xmlIsPubidChar_tab[256]; /** * xmlIsPubidChar_ch: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsPubidChar_ch(c) (xmlIsPubidChar_tab[(c)]) /** * xmlIsPubidCharQ: * @c: char to validate * * Automatically generated by genChRanges.py */ #define xmlIsPubidCharQ(c) (((c) < 0x100) ? \ xmlIsPubidChar_ch((c)) : 0) XMLPUBFUN int XMLCALL xmlIsBaseChar(unsigned int ch); XMLPUBFUN int XMLCALL xmlIsBlank(unsigned int ch); XMLPUBFUN int XMLCALL xmlIsChar(unsigned int ch); XMLPUBFUN int XMLCALL xmlIsCombining(unsigned int ch); XMLPUBFUN int XMLCALL xmlIsDigit(unsigned int ch); XMLPUBFUN int XMLCALL xmlIsExtender(unsigned int ch); XMLPUBFUN int XMLCALL xmlIsIdeographic(unsigned int ch); XMLPUBFUN int XMLCALL xmlIsPubidChar(unsigned int ch); #ifdef __cplusplus } #endif #endif /* __XML_CHVALID_H__ */ PK!libxml/nanohttp.hnu[/* * Summary: minimal HTTP implementation * Description: minimal HTTP implementation allowing to fetch resources * like external subset. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __NANO_HTTP_H__ #define __NANO_HTTP_H__ #include #ifdef LIBXML_HTTP_ENABLED #ifdef __cplusplus extern "C" { #endif XMLPUBFUN void XMLCALL xmlNanoHTTPInit (void); XMLPUBFUN void XMLCALL xmlNanoHTTPCleanup (void); XMLPUBFUN void XMLCALL xmlNanoHTTPScanProxy (const char *URL); XMLPUBFUN int XMLCALL xmlNanoHTTPFetch (const char *URL, const char *filename, char **contentType); XMLPUBFUN void * XMLCALL xmlNanoHTTPMethod (const char *URL, const char *method, const char *input, char **contentType, const char *headers, int ilen); XMLPUBFUN void * XMLCALL xmlNanoHTTPMethodRedir (const char *URL, const char *method, const char *input, char **contentType, char **redir, const char *headers, int ilen); XMLPUBFUN void * XMLCALL xmlNanoHTTPOpen (const char *URL, char **contentType); XMLPUBFUN void * XMLCALL xmlNanoHTTPOpenRedir (const char *URL, char **contentType, char **redir); XMLPUBFUN int XMLCALL xmlNanoHTTPReturnCode (void *ctx); XMLPUBFUN const char * XMLCALL xmlNanoHTTPAuthHeader (void *ctx); XMLPUBFUN const char * XMLCALL xmlNanoHTTPRedir (void *ctx); XMLPUBFUN int XMLCALL xmlNanoHTTPContentLength( void * ctx ); XMLPUBFUN const char * XMLCALL xmlNanoHTTPEncoding (void *ctx); XMLPUBFUN const char * XMLCALL xmlNanoHTTPMimeType (void *ctx); XMLPUBFUN int XMLCALL xmlNanoHTTPRead (void *ctx, void *dest, int len); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN int XMLCALL xmlNanoHTTPSave (void *ctxt, const char *filename); #endif /* LIBXML_OUTPUT_ENABLED */ XMLPUBFUN void XMLCALL xmlNanoHTTPClose (void *ctx); #ifdef __cplusplus } #endif #endif /* LIBXML_HTTP_ENABLED */ #endif /* __NANO_HTTP_H__ */ PK!׹ libxml/xinclude.hnu[/* * Summary: implementation of XInclude * Description: API to handle XInclude processing, * implements the * World Wide Web Consortium Last Call Working Draft 10 November 2003 * http://www.w3.org/TR/2003/WD-xinclude-20031110 * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XINCLUDE_H__ #define __XML_XINCLUDE_H__ #include #include #ifdef LIBXML_XINCLUDE_ENABLED #ifdef __cplusplus extern "C" { #endif /** * XINCLUDE_NS: * * Macro defining the Xinclude namespace: http://www.w3.org/2003/XInclude */ #define XINCLUDE_NS (const xmlChar *) "http://www.w3.org/2003/XInclude" /** * XINCLUDE_OLD_NS: * * Macro defining the draft Xinclude namespace: http://www.w3.org/2001/XInclude */ #define XINCLUDE_OLD_NS (const xmlChar *) "http://www.w3.org/2001/XInclude" /** * XINCLUDE_NODE: * * Macro defining "include" */ #define XINCLUDE_NODE (const xmlChar *) "include" /** * XINCLUDE_FALLBACK: * * Macro defining "fallback" */ #define XINCLUDE_FALLBACK (const xmlChar *) "fallback" /** * XINCLUDE_HREF: * * Macro defining "href" */ #define XINCLUDE_HREF (const xmlChar *) "href" /** * XINCLUDE_PARSE: * * Macro defining "parse" */ #define XINCLUDE_PARSE (const xmlChar *) "parse" /** * XINCLUDE_PARSE_XML: * * Macro defining "xml" */ #define XINCLUDE_PARSE_XML (const xmlChar *) "xml" /** * XINCLUDE_PARSE_TEXT: * * Macro defining "text" */ #define XINCLUDE_PARSE_TEXT (const xmlChar *) "text" /** * XINCLUDE_PARSE_ENCODING: * * Macro defining "encoding" */ #define XINCLUDE_PARSE_ENCODING (const xmlChar *) "encoding" /** * XINCLUDE_PARSE_XPOINTER: * * Macro defining "xpointer" */ #define XINCLUDE_PARSE_XPOINTER (const xmlChar *) "xpointer" typedef struct _xmlXIncludeCtxt xmlXIncludeCtxt; typedef xmlXIncludeCtxt *xmlXIncludeCtxtPtr; /* * standalone processing */ XMLPUBFUN int XMLCALL xmlXIncludeProcess (xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlXIncludeProcessFlags (xmlDocPtr doc, int flags); XMLPUBFUN int XMLCALL xmlXIncludeProcessFlagsData(xmlDocPtr doc, int flags, void *data); XMLPUBFUN int XMLCALL xmlXIncludeProcessTreeFlagsData(xmlNodePtr tree, int flags, void *data); XMLPUBFUN int XMLCALL xmlXIncludeProcessTree (xmlNodePtr tree); XMLPUBFUN int XMLCALL xmlXIncludeProcessTreeFlags(xmlNodePtr tree, int flags); /* * contextual processing */ XMLPUBFUN xmlXIncludeCtxtPtr XMLCALL xmlXIncludeNewContext (xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlXIncludeSetFlags (xmlXIncludeCtxtPtr ctxt, int flags); XMLPUBFUN void XMLCALL xmlXIncludeFreeContext (xmlXIncludeCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlXIncludeProcessNode (xmlXIncludeCtxtPtr ctxt, xmlNodePtr tree); #ifdef __cplusplus } #endif #endif /* LIBXML_XINCLUDE_ENABLED */ #endif /* __XML_XINCLUDE_H__ */ PK!McƲlibxml/xlink.hnu[/* * Summary: unfinished XLink detection module * Description: unfinished XLink detection module * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XLINK_H__ #define __XML_XLINK_H__ #include #include #ifdef LIBXML_XPTR_ENABLED #ifdef __cplusplus extern "C" { #endif /** * Various defines for the various Link properties. * * NOTE: the link detection layer will try to resolve QName expansion * of namespaces. If "foo" is the prefix for "http://foo.com/" * then the link detection layer will expand role="foo:myrole" * to "http://foo.com/:myrole". * NOTE: the link detection layer will expand URI-References found on * href attributes by using the base mechanism if found. */ typedef xmlChar *xlinkHRef; typedef xmlChar *xlinkRole; typedef xmlChar *xlinkTitle; typedef enum { XLINK_TYPE_NONE = 0, XLINK_TYPE_SIMPLE, XLINK_TYPE_EXTENDED, XLINK_TYPE_EXTENDED_SET } xlinkType; typedef enum { XLINK_SHOW_NONE = 0, XLINK_SHOW_NEW, XLINK_SHOW_EMBED, XLINK_SHOW_REPLACE } xlinkShow; typedef enum { XLINK_ACTUATE_NONE = 0, XLINK_ACTUATE_AUTO, XLINK_ACTUATE_ONREQUEST } xlinkActuate; /** * xlinkNodeDetectFunc: * @ctx: user data pointer * @node: the node to check * * This is the prototype for the link detection routine. * It calls the default link detection callbacks upon link detection. */ typedef void (*xlinkNodeDetectFunc) (void *ctx, xmlNodePtr node); /* * The link detection module interact with the upper layers using * a set of callback registered at parsing time. */ /** * xlinkSimpleLinkFunk: * @ctx: user data pointer * @node: the node carrying the link * @href: the target of the link * @role: the role string * @title: the link title * * This is the prototype for a simple link detection callback. */ typedef void (*xlinkSimpleLinkFunk) (void *ctx, xmlNodePtr node, const xlinkHRef href, const xlinkRole role, const xlinkTitle title); /** * xlinkExtendedLinkFunk: * @ctx: user data pointer * @node: the node carrying the link * @nbLocators: the number of locators detected on the link * @hrefs: pointer to the array of locator hrefs * @roles: pointer to the array of locator roles * @nbArcs: the number of arcs detected on the link * @from: pointer to the array of source roles found on the arcs * @to: pointer to the array of target roles found on the arcs * @show: array of values for the show attributes found on the arcs * @actuate: array of values for the actuate attributes found on the arcs * @nbTitles: the number of titles detected on the link * @title: array of titles detected on the link * @langs: array of xml:lang values for the titles * * This is the prototype for a extended link detection callback. */ typedef void (*xlinkExtendedLinkFunk)(void *ctx, xmlNodePtr node, int nbLocators, const xlinkHRef *hrefs, const xlinkRole *roles, int nbArcs, const xlinkRole *from, const xlinkRole *to, xlinkShow *show, xlinkActuate *actuate, int nbTitles, const xlinkTitle *titles, const xmlChar **langs); /** * xlinkExtendedLinkSetFunk: * @ctx: user data pointer * @node: the node carrying the link * @nbLocators: the number of locators detected on the link * @hrefs: pointer to the array of locator hrefs * @roles: pointer to the array of locator roles * @nbTitles: the number of titles detected on the link * @title: array of titles detected on the link * @langs: array of xml:lang values for the titles * * This is the prototype for a extended link set detection callback. */ typedef void (*xlinkExtendedLinkSetFunk) (void *ctx, xmlNodePtr node, int nbLocators, const xlinkHRef *hrefs, const xlinkRole *roles, int nbTitles, const xlinkTitle *titles, const xmlChar **langs); /** * This is the structure containing a set of Links detection callbacks. * * There is no default xlink callbacks, if one want to get link * recognition activated, those call backs must be provided before parsing. */ typedef struct _xlinkHandler xlinkHandler; typedef xlinkHandler *xlinkHandlerPtr; struct _xlinkHandler { xlinkSimpleLinkFunk simple; xlinkExtendedLinkFunk extended; xlinkExtendedLinkSetFunk set; }; /* * The default detection routine, can be overridden, they call the default * detection callbacks. */ XMLPUBFUN xlinkNodeDetectFunc XMLCALL xlinkGetDefaultDetect (void); XMLPUBFUN void XMLCALL xlinkSetDefaultDetect (xlinkNodeDetectFunc func); /* * Routines to set/get the default handlers. */ XMLPUBFUN xlinkHandlerPtr XMLCALL xlinkGetDefaultHandler (void); XMLPUBFUN void XMLCALL xlinkSetDefaultHandler (xlinkHandlerPtr handler); /* * Link detection module itself. */ XMLPUBFUN xlinkType XMLCALL xlinkIsLink (xmlDocPtr doc, xmlNodePtr node); #ifdef __cplusplus } #endif #endif /* LIBXML_XPTR_ENABLED */ #endif /* __XML_XLINK_H__ */ PK!d4RRlibxml/xmlregexp.hnu[/* * Summary: regular expressions handling * Description: basic API for libxml regular expressions handling used * for XML Schemas and validation. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_REGEXP_H__ #define __XML_REGEXP_H__ #include #ifdef LIBXML_REGEXP_ENABLED #ifdef __cplusplus extern "C" { #endif /** * xmlRegexpPtr: * * A libxml regular expression, they can actually be far more complex * thank the POSIX regex expressions. */ typedef struct _xmlRegexp xmlRegexp; typedef xmlRegexp *xmlRegexpPtr; /** * xmlRegExecCtxtPtr: * * A libxml progressive regular expression evaluation context */ typedef struct _xmlRegExecCtxt xmlRegExecCtxt; typedef xmlRegExecCtxt *xmlRegExecCtxtPtr; #ifdef __cplusplus } #endif #include #include #ifdef __cplusplus extern "C" { #endif /* * The POSIX like API */ XMLPUBFUN xmlRegexpPtr XMLCALL xmlRegexpCompile (const xmlChar *regexp); XMLPUBFUN void XMLCALL xmlRegFreeRegexp(xmlRegexpPtr regexp); XMLPUBFUN int XMLCALL xmlRegexpExec (xmlRegexpPtr comp, const xmlChar *value); XMLPUBFUN void XMLCALL xmlRegexpPrint (FILE *output, xmlRegexpPtr regexp); XMLPUBFUN int XMLCALL xmlRegexpIsDeterminist(xmlRegexpPtr comp); /** * xmlRegExecCallbacks: * @exec: the regular expression context * @token: the current token string * @transdata: transition data * @inputdata: input data * * Callback function when doing a transition in the automata */ typedef void (*xmlRegExecCallbacks) (xmlRegExecCtxtPtr exec, const xmlChar *token, void *transdata, void *inputdata); /* * The progressive API */ XMLPUBFUN xmlRegExecCtxtPtr XMLCALL xmlRegNewExecCtxt (xmlRegexpPtr comp, xmlRegExecCallbacks callback, void *data); XMLPUBFUN void XMLCALL xmlRegFreeExecCtxt (xmlRegExecCtxtPtr exec); XMLPUBFUN int XMLCALL xmlRegExecPushString(xmlRegExecCtxtPtr exec, const xmlChar *value, void *data); XMLPUBFUN int XMLCALL xmlRegExecPushString2(xmlRegExecCtxtPtr exec, const xmlChar *value, const xmlChar *value2, void *data); XMLPUBFUN int XMLCALL xmlRegExecNextValues(xmlRegExecCtxtPtr exec, int *nbval, int *nbneg, xmlChar **values, int *terminal); XMLPUBFUN int XMLCALL xmlRegExecErrInfo (xmlRegExecCtxtPtr exec, const xmlChar **string, int *nbval, int *nbneg, xmlChar **values, int *terminal); #ifdef LIBXML_EXPR_ENABLED /* * Formal regular expression handling * Its goal is to do some formal work on content models */ /* expressions are used within a context */ typedef struct _xmlExpCtxt xmlExpCtxt; typedef xmlExpCtxt *xmlExpCtxtPtr; XMLPUBFUN void XMLCALL xmlExpFreeCtxt (xmlExpCtxtPtr ctxt); XMLPUBFUN xmlExpCtxtPtr XMLCALL xmlExpNewCtxt (int maxNodes, xmlDictPtr dict); XMLPUBFUN int XMLCALL xmlExpCtxtNbNodes(xmlExpCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlExpCtxtNbCons(xmlExpCtxtPtr ctxt); /* Expressions are trees but the tree is opaque */ typedef struct _xmlExpNode xmlExpNode; typedef xmlExpNode *xmlExpNodePtr; typedef enum { XML_EXP_EMPTY = 0, XML_EXP_FORBID = 1, XML_EXP_ATOM = 2, XML_EXP_SEQ = 3, XML_EXP_OR = 4, XML_EXP_COUNT = 5 } xmlExpNodeType; /* * 2 core expressions shared by all for the empty language set * and for the set with just the empty token */ XMLPUBVAR xmlExpNodePtr forbiddenExp; XMLPUBVAR xmlExpNodePtr emptyExp; /* * Expressions are reference counted internally */ XMLPUBFUN void XMLCALL xmlExpFree (xmlExpCtxtPtr ctxt, xmlExpNodePtr expr); XMLPUBFUN void XMLCALL xmlExpRef (xmlExpNodePtr expr); /* * constructors can be either manual or from a string */ XMLPUBFUN xmlExpNodePtr XMLCALL xmlExpParse (xmlExpCtxtPtr ctxt, const char *expr); XMLPUBFUN xmlExpNodePtr XMLCALL xmlExpNewAtom (xmlExpCtxtPtr ctxt, const xmlChar *name, int len); XMLPUBFUN xmlExpNodePtr XMLCALL xmlExpNewOr (xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right); XMLPUBFUN xmlExpNodePtr XMLCALL xmlExpNewSeq (xmlExpCtxtPtr ctxt, xmlExpNodePtr left, xmlExpNodePtr right); XMLPUBFUN xmlExpNodePtr XMLCALL xmlExpNewRange (xmlExpCtxtPtr ctxt, xmlExpNodePtr subset, int min, int max); /* * The really interesting APIs */ XMLPUBFUN int XMLCALL xmlExpIsNillable(xmlExpNodePtr expr); XMLPUBFUN int XMLCALL xmlExpMaxToken (xmlExpNodePtr expr); XMLPUBFUN int XMLCALL xmlExpGetLanguage(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, const xmlChar**langList, int len); XMLPUBFUN int XMLCALL xmlExpGetStart (xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, const xmlChar**tokList, int len); XMLPUBFUN xmlExpNodePtr XMLCALL xmlExpStringDerive(xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, const xmlChar *str, int len); XMLPUBFUN xmlExpNodePtr XMLCALL xmlExpExpDerive (xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, xmlExpNodePtr sub); XMLPUBFUN int XMLCALL xmlExpSubsume (xmlExpCtxtPtr ctxt, xmlExpNodePtr expr, xmlExpNodePtr sub); XMLPUBFUN void XMLCALL xmlExpDump (xmlBufferPtr buf, xmlExpNodePtr expr); #endif /* LIBXML_EXPR_ENABLED */ #ifdef __cplusplus } #endif #endif /* LIBXML_REGEXP_ENABLED */ #endif /*__XML_REGEXP_H__ */ PK!y**libxml/catalog.hnu[/** * Summary: interfaces to the Catalog handling system * Description: the catalog module implements the support for * XML Catalogs and SGML catalogs * * SGML Open Technical Resolution TR9401:1997. * http://www.jclark.com/sp/catalog.htm * * XML Catalogs Working Draft 06 August 2001 * http://www.oasis-open.org/committees/entity/spec-2001-08-06.html * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_CATALOG_H__ #define __XML_CATALOG_H__ #include #include #include #include #ifdef LIBXML_CATALOG_ENABLED #ifdef __cplusplus extern "C" { #endif /** * XML_CATALOGS_NAMESPACE: * * The namespace for the XML Catalogs elements. */ #define XML_CATALOGS_NAMESPACE \ (const xmlChar *) "urn:oasis:names:tc:entity:xmlns:xml:catalog" /** * XML_CATALOG_PI: * * The specific XML Catalog Processing Instruction name. */ #define XML_CATALOG_PI \ (const xmlChar *) "oasis-xml-catalog" /* * The API is voluntarily limited to general cataloging. */ typedef enum { XML_CATA_PREFER_NONE = 0, XML_CATA_PREFER_PUBLIC = 1, XML_CATA_PREFER_SYSTEM } xmlCatalogPrefer; typedef enum { XML_CATA_ALLOW_NONE = 0, XML_CATA_ALLOW_GLOBAL = 1, XML_CATA_ALLOW_DOCUMENT = 2, XML_CATA_ALLOW_ALL = 3 } xmlCatalogAllow; typedef struct _xmlCatalog xmlCatalog; typedef xmlCatalog *xmlCatalogPtr; /* * Operations on a given catalog. */ XMLPUBFUN xmlCatalogPtr XMLCALL xmlNewCatalog (int sgml); XMLPUBFUN xmlCatalogPtr XMLCALL xmlLoadACatalog (const char *filename); XMLPUBFUN xmlCatalogPtr XMLCALL xmlLoadSGMLSuperCatalog (const char *filename); XMLPUBFUN int XMLCALL xmlConvertSGMLCatalog (xmlCatalogPtr catal); XMLPUBFUN int XMLCALL xmlACatalogAdd (xmlCatalogPtr catal, const xmlChar *type, const xmlChar *orig, const xmlChar *replace); XMLPUBFUN int XMLCALL xmlACatalogRemove (xmlCatalogPtr catal, const xmlChar *value); XMLPUBFUN xmlChar * XMLCALL xmlACatalogResolve (xmlCatalogPtr catal, const xmlChar *pubID, const xmlChar *sysID); XMLPUBFUN xmlChar * XMLCALL xmlACatalogResolveSystem(xmlCatalogPtr catal, const xmlChar *sysID); XMLPUBFUN xmlChar * XMLCALL xmlACatalogResolvePublic(xmlCatalogPtr catal, const xmlChar *pubID); XMLPUBFUN xmlChar * XMLCALL xmlACatalogResolveURI (xmlCatalogPtr catal, const xmlChar *URI); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlACatalogDump (xmlCatalogPtr catal, FILE *out); #endif /* LIBXML_OUTPUT_ENABLED */ XMLPUBFUN void XMLCALL xmlFreeCatalog (xmlCatalogPtr catal); XMLPUBFUN int XMLCALL xmlCatalogIsEmpty (xmlCatalogPtr catal); /* * Global operations. */ XMLPUBFUN void XMLCALL xmlInitializeCatalog (void); XMLPUBFUN int XMLCALL xmlLoadCatalog (const char *filename); XMLPUBFUN void XMLCALL xmlLoadCatalogs (const char *paths); XMLPUBFUN void XMLCALL xmlCatalogCleanup (void); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlCatalogDump (FILE *out); #endif /* LIBXML_OUTPUT_ENABLED */ XMLPUBFUN xmlChar * XMLCALL xmlCatalogResolve (const xmlChar *pubID, const xmlChar *sysID); XMLPUBFUN xmlChar * XMLCALL xmlCatalogResolveSystem (const xmlChar *sysID); XMLPUBFUN xmlChar * XMLCALL xmlCatalogResolvePublic (const xmlChar *pubID); XMLPUBFUN xmlChar * XMLCALL xmlCatalogResolveURI (const xmlChar *URI); XMLPUBFUN int XMLCALL xmlCatalogAdd (const xmlChar *type, const xmlChar *orig, const xmlChar *replace); XMLPUBFUN int XMLCALL xmlCatalogRemove (const xmlChar *value); XMLPUBFUN xmlDocPtr XMLCALL xmlParseCatalogFile (const char *filename); XMLPUBFUN int XMLCALL xmlCatalogConvert (void); /* * Strictly minimal interfaces for per-document catalogs used * by the parser. */ XMLPUBFUN void XMLCALL xmlCatalogFreeLocal (void *catalogs); XMLPUBFUN void * XMLCALL xmlCatalogAddLocal (void *catalogs, const xmlChar *URL); XMLPUBFUN xmlChar * XMLCALL xmlCatalogLocalResolve (void *catalogs, const xmlChar *pubID, const xmlChar *sysID); XMLPUBFUN xmlChar * XMLCALL xmlCatalogLocalResolveURI(void *catalogs, const xmlChar *URI); /* * Preference settings. */ XMLPUBFUN int XMLCALL xmlCatalogSetDebug (int level); XMLPUBFUN xmlCatalogPrefer XMLCALL xmlCatalogSetDefaultPrefer(xmlCatalogPrefer prefer); XMLPUBFUN void XMLCALL xmlCatalogSetDefaults (xmlCatalogAllow allow); XMLPUBFUN xmlCatalogAllow XMLCALL xmlCatalogGetDefaults (void); /* DEPRECATED interfaces */ XMLPUBFUN const xmlChar * XMLCALL xmlCatalogGetSystem (const xmlChar *sysID); XMLPUBFUN const xmlChar * XMLCALL xmlCatalogGetPublic (const xmlChar *pubID); #ifdef __cplusplus } #endif #endif /* LIBXML_CATALOG_ENABLED */ #endif /* __XML_CATALOG_H__ */ PK!m>>libxml/HTMLtree.hnu[/* * Summary: specific APIs to process HTML tree, especially serialization * Description: this module implements a few function needed to process * tree in an HTML specific way. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __HTML_TREE_H__ #define __HTML_TREE_H__ #include #include #include #include #ifdef LIBXML_HTML_ENABLED #ifdef __cplusplus extern "C" { #endif /** * HTML_TEXT_NODE: * * Macro. A text node in a HTML document is really implemented * the same way as a text node in an XML document. */ #define HTML_TEXT_NODE XML_TEXT_NODE /** * HTML_ENTITY_REF_NODE: * * Macro. An entity reference in a HTML document is really implemented * the same way as an entity reference in an XML document. */ #define HTML_ENTITY_REF_NODE XML_ENTITY_REF_NODE /** * HTML_COMMENT_NODE: * * Macro. A comment in a HTML document is really implemented * the same way as a comment in an XML document. */ #define HTML_COMMENT_NODE XML_COMMENT_NODE /** * HTML_PRESERVE_NODE: * * Macro. A preserved node in a HTML document is really implemented * the same way as a CDATA section in an XML document. */ #define HTML_PRESERVE_NODE XML_CDATA_SECTION_NODE /** * HTML_PI_NODE: * * Macro. A processing instruction in a HTML document is really implemented * the same way as a processing instruction in an XML document. */ #define HTML_PI_NODE XML_PI_NODE XMLPUBFUN htmlDocPtr XMLCALL htmlNewDoc (const xmlChar *URI, const xmlChar *ExternalID); XMLPUBFUN htmlDocPtr XMLCALL htmlNewDocNoDtD (const xmlChar *URI, const xmlChar *ExternalID); XMLPUBFUN const xmlChar * XMLCALL htmlGetMetaEncoding (htmlDocPtr doc); XMLPUBFUN int XMLCALL htmlSetMetaEncoding (htmlDocPtr doc, const xmlChar *encoding); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL htmlDocDumpMemory (xmlDocPtr cur, xmlChar **mem, int *size); XMLPUBFUN void XMLCALL htmlDocDumpMemoryFormat (xmlDocPtr cur, xmlChar **mem, int *size, int format); XMLPUBFUN int XMLCALL htmlDocDump (FILE *f, xmlDocPtr cur); XMLPUBFUN int XMLCALL htmlSaveFile (const char *filename, xmlDocPtr cur); XMLPUBFUN int XMLCALL htmlNodeDump (xmlBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur); XMLPUBFUN void XMLCALL htmlNodeDumpFile (FILE *out, xmlDocPtr doc, xmlNodePtr cur); XMLPUBFUN int XMLCALL htmlNodeDumpFileFormat (FILE *out, xmlDocPtr doc, xmlNodePtr cur, const char *encoding, int format); XMLPUBFUN int XMLCALL htmlSaveFileEnc (const char *filename, xmlDocPtr cur, const char *encoding); XMLPUBFUN int XMLCALL htmlSaveFileFormat (const char *filename, xmlDocPtr cur, const char *encoding, int format); XMLPUBFUN void XMLCALL htmlNodeDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, const char *encoding, int format); XMLPUBFUN void XMLCALL htmlDocContentDumpOutput(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding); XMLPUBFUN void XMLCALL htmlDocContentDumpFormatOutput(xmlOutputBufferPtr buf, xmlDocPtr cur, const char *encoding, int format); XMLPUBFUN void XMLCALL htmlNodeDumpOutput (xmlOutputBufferPtr buf, xmlDocPtr doc, xmlNodePtr cur, const char *encoding); #endif /* LIBXML_OUTPUT_ENABLED */ XMLPUBFUN int XMLCALL htmlIsBooleanAttr (const xmlChar *name); #ifdef __cplusplus } #endif #endif /* LIBXML_HTML_ENABLED */ #endif /* __HTML_TREE_H__ */ PK!libxml/__init__.pynu[PK!:-5  libxml/debugXML.hnu[/* * Summary: Tree debugging APIs * Description: Interfaces to a set of routines used for debugging the tree * produced by the XML parser. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __DEBUG_XML__ #define __DEBUG_XML__ #include #include #include #ifdef LIBXML_DEBUG_ENABLED #include #ifdef __cplusplus extern "C" { #endif /* * The standard Dump routines. */ XMLPUBFUN void XMLCALL xmlDebugDumpString (FILE *output, const xmlChar *str); XMLPUBFUN void XMLCALL xmlDebugDumpAttr (FILE *output, xmlAttrPtr attr, int depth); XMLPUBFUN void XMLCALL xmlDebugDumpAttrList (FILE *output, xmlAttrPtr attr, int depth); XMLPUBFUN void XMLCALL xmlDebugDumpOneNode (FILE *output, xmlNodePtr node, int depth); XMLPUBFUN void XMLCALL xmlDebugDumpNode (FILE *output, xmlNodePtr node, int depth); XMLPUBFUN void XMLCALL xmlDebugDumpNodeList (FILE *output, xmlNodePtr node, int depth); XMLPUBFUN void XMLCALL xmlDebugDumpDocumentHead(FILE *output, xmlDocPtr doc); XMLPUBFUN void XMLCALL xmlDebugDumpDocument (FILE *output, xmlDocPtr doc); XMLPUBFUN void XMLCALL xmlDebugDumpDTD (FILE *output, xmlDtdPtr dtd); XMLPUBFUN void XMLCALL xmlDebugDumpEntities (FILE *output, xmlDocPtr doc); /**************************************************************** * * * Checking routines * * * ****************************************************************/ XMLPUBFUN int XMLCALL xmlDebugCheckDocument (FILE * output, xmlDocPtr doc); /**************************************************************** * * * XML shell helpers * * * ****************************************************************/ XMLPUBFUN void XMLCALL xmlLsOneNode (FILE *output, xmlNodePtr node); XMLPUBFUN int XMLCALL xmlLsCountNode (xmlNodePtr node); XMLPUBFUN const char * XMLCALL xmlBoolToText (int boolval); /**************************************************************** * * * The XML shell related structures and functions * * * ****************************************************************/ #ifdef LIBXML_XPATH_ENABLED /** * xmlShellReadlineFunc: * @prompt: a string prompt * * This is a generic signature for the XML shell input function. * * Returns a string which will be freed by the Shell. */ typedef char * (* xmlShellReadlineFunc)(char *prompt); /** * xmlShellCtxt: * * A debugging shell context. * TODO: add the defined function tables. */ typedef struct _xmlShellCtxt xmlShellCtxt; typedef xmlShellCtxt *xmlShellCtxtPtr; struct _xmlShellCtxt { char *filename; xmlDocPtr doc; xmlNodePtr node; xmlXPathContextPtr pctxt; int loaded; FILE *output; xmlShellReadlineFunc input; }; /** * xmlShellCmd: * @ctxt: a shell context * @arg: a string argument * @node: a first node * @node2: a second node * * This is a generic signature for the XML shell functions. * * Returns an int, negative returns indicating errors. */ typedef int (* xmlShellCmd) (xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node, xmlNodePtr node2); XMLPUBFUN void XMLCALL xmlShellPrintXPathError (int errorType, const char *arg); XMLPUBFUN void XMLCALL xmlShellPrintXPathResult(xmlXPathObjectPtr list); XMLPUBFUN int XMLCALL xmlShellList (xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node, xmlNodePtr node2); XMLPUBFUN int XMLCALL xmlShellBase (xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node, xmlNodePtr node2); XMLPUBFUN int XMLCALL xmlShellDir (xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node, xmlNodePtr node2); XMLPUBFUN int XMLCALL xmlShellLoad (xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, xmlNodePtr node2); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlShellPrintNode (xmlNodePtr node); XMLPUBFUN int XMLCALL xmlShellCat (xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr node, xmlNodePtr node2); XMLPUBFUN int XMLCALL xmlShellWrite (xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, xmlNodePtr node2); XMLPUBFUN int XMLCALL xmlShellSave (xmlShellCtxtPtr ctxt, char *filename, xmlNodePtr node, xmlNodePtr node2); #endif /* LIBXML_OUTPUT_ENABLED */ #ifdef LIBXML_VALID_ENABLED XMLPUBFUN int XMLCALL xmlShellValidate (xmlShellCtxtPtr ctxt, char *dtd, xmlNodePtr node, xmlNodePtr node2); #endif /* LIBXML_VALID_ENABLED */ XMLPUBFUN int XMLCALL xmlShellDu (xmlShellCtxtPtr ctxt, char *arg, xmlNodePtr tree, xmlNodePtr node2); XMLPUBFUN int XMLCALL xmlShellPwd (xmlShellCtxtPtr ctxt, char *buffer, xmlNodePtr node, xmlNodePtr node2); /* * The Shell interface. */ XMLPUBFUN void XMLCALL xmlShell (xmlDocPtr doc, char *filename, xmlShellReadlineFunc input, FILE *output); #endif /* LIBXML_XPATH_ENABLED */ #ifdef __cplusplus } #endif #endif /* LIBXML_DEBUG_ENABLED */ #endif /* __DEBUG_XML__ */ PK!UT ' 'libxml/xmlunicode.hnu[/* * Summary: Unicode character APIs * Description: API for the Unicode character APIs * * This file is automatically generated from the * UCS description files of the Unicode Character Database * http://www.unicode.org/Public/4.0-Update1/UCD-4.0.1.html * using the genUnicode.py Python script. * * Generation date: Mon Mar 27 11:09:52 2006 * Sources: Blocks-4.0.1.txt UnicodeData-4.0.1.txt * Author: Daniel Veillard */ #ifndef __XML_UNICODE_H__ #define __XML_UNICODE_H__ #include #ifdef LIBXML_UNICODE_ENABLED #ifdef __cplusplus extern "C" { #endif XMLPUBFUN int XMLCALL xmlUCSIsAegeanNumbers (int code); XMLPUBFUN int XMLCALL xmlUCSIsAlphabeticPresentationForms (int code); XMLPUBFUN int XMLCALL xmlUCSIsArabic (int code); XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsA (int code); XMLPUBFUN int XMLCALL xmlUCSIsArabicPresentationFormsB (int code); XMLPUBFUN int XMLCALL xmlUCSIsArmenian (int code); XMLPUBFUN int XMLCALL xmlUCSIsArrows (int code); XMLPUBFUN int XMLCALL xmlUCSIsBasicLatin (int code); XMLPUBFUN int XMLCALL xmlUCSIsBengali (int code); XMLPUBFUN int XMLCALL xmlUCSIsBlockElements (int code); XMLPUBFUN int XMLCALL xmlUCSIsBopomofo (int code); XMLPUBFUN int XMLCALL xmlUCSIsBopomofoExtended (int code); XMLPUBFUN int XMLCALL xmlUCSIsBoxDrawing (int code); XMLPUBFUN int XMLCALL xmlUCSIsBraillePatterns (int code); XMLPUBFUN int XMLCALL xmlUCSIsBuhid (int code); XMLPUBFUN int XMLCALL xmlUCSIsByzantineMusicalSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibility (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityForms (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographs (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKCompatibilityIdeographsSupplement (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKRadicalsSupplement (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKSymbolsandPunctuation (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographs (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionA (int code); XMLPUBFUN int XMLCALL xmlUCSIsCJKUnifiedIdeographsExtensionB (int code); XMLPUBFUN int XMLCALL xmlUCSIsCherokee (int code); XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarks (int code); XMLPUBFUN int XMLCALL xmlUCSIsCombiningDiacriticalMarksforSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsCombiningHalfMarks (int code); XMLPUBFUN int XMLCALL xmlUCSIsCombiningMarksforSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsControlPictures (int code); XMLPUBFUN int XMLCALL xmlUCSIsCurrencySymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsCypriotSyllabary (int code); XMLPUBFUN int XMLCALL xmlUCSIsCyrillic (int code); XMLPUBFUN int XMLCALL xmlUCSIsCyrillicSupplement (int code); XMLPUBFUN int XMLCALL xmlUCSIsDeseret (int code); XMLPUBFUN int XMLCALL xmlUCSIsDevanagari (int code); XMLPUBFUN int XMLCALL xmlUCSIsDingbats (int code); XMLPUBFUN int XMLCALL xmlUCSIsEnclosedAlphanumerics (int code); XMLPUBFUN int XMLCALL xmlUCSIsEnclosedCJKLettersandMonths (int code); XMLPUBFUN int XMLCALL xmlUCSIsEthiopic (int code); XMLPUBFUN int XMLCALL xmlUCSIsGeneralPunctuation (int code); XMLPUBFUN int XMLCALL xmlUCSIsGeometricShapes (int code); XMLPUBFUN int XMLCALL xmlUCSIsGeorgian (int code); XMLPUBFUN int XMLCALL xmlUCSIsGothic (int code); XMLPUBFUN int XMLCALL xmlUCSIsGreek (int code); XMLPUBFUN int XMLCALL xmlUCSIsGreekExtended (int code); XMLPUBFUN int XMLCALL xmlUCSIsGreekandCoptic (int code); XMLPUBFUN int XMLCALL xmlUCSIsGujarati (int code); XMLPUBFUN int XMLCALL xmlUCSIsGurmukhi (int code); XMLPUBFUN int XMLCALL xmlUCSIsHalfwidthandFullwidthForms (int code); XMLPUBFUN int XMLCALL xmlUCSIsHangulCompatibilityJamo (int code); XMLPUBFUN int XMLCALL xmlUCSIsHangulJamo (int code); XMLPUBFUN int XMLCALL xmlUCSIsHangulSyllables (int code); XMLPUBFUN int XMLCALL xmlUCSIsHanunoo (int code); XMLPUBFUN int XMLCALL xmlUCSIsHebrew (int code); XMLPUBFUN int XMLCALL xmlUCSIsHighPrivateUseSurrogates (int code); XMLPUBFUN int XMLCALL xmlUCSIsHighSurrogates (int code); XMLPUBFUN int XMLCALL xmlUCSIsHiragana (int code); XMLPUBFUN int XMLCALL xmlUCSIsIPAExtensions (int code); XMLPUBFUN int XMLCALL xmlUCSIsIdeographicDescriptionCharacters (int code); XMLPUBFUN int XMLCALL xmlUCSIsKanbun (int code); XMLPUBFUN int XMLCALL xmlUCSIsKangxiRadicals (int code); XMLPUBFUN int XMLCALL xmlUCSIsKannada (int code); XMLPUBFUN int XMLCALL xmlUCSIsKatakana (int code); XMLPUBFUN int XMLCALL xmlUCSIsKatakanaPhoneticExtensions (int code); XMLPUBFUN int XMLCALL xmlUCSIsKhmer (int code); XMLPUBFUN int XMLCALL xmlUCSIsKhmerSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsLao (int code); XMLPUBFUN int XMLCALL xmlUCSIsLatin1Supplement (int code); XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedA (int code); XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedB (int code); XMLPUBFUN int XMLCALL xmlUCSIsLatinExtendedAdditional (int code); XMLPUBFUN int XMLCALL xmlUCSIsLetterlikeSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsLimbu (int code); XMLPUBFUN int XMLCALL xmlUCSIsLinearBIdeograms (int code); XMLPUBFUN int XMLCALL xmlUCSIsLinearBSyllabary (int code); XMLPUBFUN int XMLCALL xmlUCSIsLowSurrogates (int code); XMLPUBFUN int XMLCALL xmlUCSIsMalayalam (int code); XMLPUBFUN int XMLCALL xmlUCSIsMathematicalAlphanumericSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsMathematicalOperators (int code); XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsA (int code); XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousMathematicalSymbolsB (int code); XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousSymbolsandArrows (int code); XMLPUBFUN int XMLCALL xmlUCSIsMiscellaneousTechnical (int code); XMLPUBFUN int XMLCALL xmlUCSIsMongolian (int code); XMLPUBFUN int XMLCALL xmlUCSIsMusicalSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsMyanmar (int code); XMLPUBFUN int XMLCALL xmlUCSIsNumberForms (int code); XMLPUBFUN int XMLCALL xmlUCSIsOgham (int code); XMLPUBFUN int XMLCALL xmlUCSIsOldItalic (int code); XMLPUBFUN int XMLCALL xmlUCSIsOpticalCharacterRecognition (int code); XMLPUBFUN int XMLCALL xmlUCSIsOriya (int code); XMLPUBFUN int XMLCALL xmlUCSIsOsmanya (int code); XMLPUBFUN int XMLCALL xmlUCSIsPhoneticExtensions (int code); XMLPUBFUN int XMLCALL xmlUCSIsPrivateUse (int code); XMLPUBFUN int XMLCALL xmlUCSIsPrivateUseArea (int code); XMLPUBFUN int XMLCALL xmlUCSIsRunic (int code); XMLPUBFUN int XMLCALL xmlUCSIsShavian (int code); XMLPUBFUN int XMLCALL xmlUCSIsSinhala (int code); XMLPUBFUN int XMLCALL xmlUCSIsSmallFormVariants (int code); XMLPUBFUN int XMLCALL xmlUCSIsSpacingModifierLetters (int code); XMLPUBFUN int XMLCALL xmlUCSIsSpecials (int code); XMLPUBFUN int XMLCALL xmlUCSIsSuperscriptsandSubscripts (int code); XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsA (int code); XMLPUBFUN int XMLCALL xmlUCSIsSupplementalArrowsB (int code); XMLPUBFUN int XMLCALL xmlUCSIsSupplementalMathematicalOperators (int code); XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaA (int code); XMLPUBFUN int XMLCALL xmlUCSIsSupplementaryPrivateUseAreaB (int code); XMLPUBFUN int XMLCALL xmlUCSIsSyriac (int code); XMLPUBFUN int XMLCALL xmlUCSIsTagalog (int code); XMLPUBFUN int XMLCALL xmlUCSIsTagbanwa (int code); XMLPUBFUN int XMLCALL xmlUCSIsTags (int code); XMLPUBFUN int XMLCALL xmlUCSIsTaiLe (int code); XMLPUBFUN int XMLCALL xmlUCSIsTaiXuanJingSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsTamil (int code); XMLPUBFUN int XMLCALL xmlUCSIsTelugu (int code); XMLPUBFUN int XMLCALL xmlUCSIsThaana (int code); XMLPUBFUN int XMLCALL xmlUCSIsThai (int code); XMLPUBFUN int XMLCALL xmlUCSIsTibetan (int code); XMLPUBFUN int XMLCALL xmlUCSIsUgaritic (int code); XMLPUBFUN int XMLCALL xmlUCSIsUnifiedCanadianAboriginalSyllabics (int code); XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectors (int code); XMLPUBFUN int XMLCALL xmlUCSIsVariationSelectorsSupplement (int code); XMLPUBFUN int XMLCALL xmlUCSIsYiRadicals (int code); XMLPUBFUN int XMLCALL xmlUCSIsYiSyllables (int code); XMLPUBFUN int XMLCALL xmlUCSIsYijingHexagramSymbols (int code); XMLPUBFUN int XMLCALL xmlUCSIsBlock (int code, const char *block); XMLPUBFUN int XMLCALL xmlUCSIsCatC (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatCc (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatCf (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatCo (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatCs (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatL (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatLl (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatLm (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatLo (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatLt (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatLu (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatM (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatMc (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatMe (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatMn (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatN (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatNd (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatNl (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatNo (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatP (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatPc (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatPd (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatPe (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatPf (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatPi (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatPo (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatPs (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatS (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatSc (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatSk (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatSm (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatSo (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatZ (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatZl (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatZp (int code); XMLPUBFUN int XMLCALL xmlUCSIsCatZs (int code); XMLPUBFUN int XMLCALL xmlUCSIsCat (int code, const char *cat); #ifdef __cplusplus } #endif #endif /* LIBXML_UNICODE_ENABLED */ #endif /* __XML_UNICODE_H__ */ PK!O;4N9N9libxml/globals.hnu[/* * Summary: interface for all global variables of the library * Description: all the global variables and thread handling for * those variables is handled by this module. * * The bottom of this file is automatically generated by build_glob.py * based on the description file global.data * * Copy: See Copyright for the status of this software. * * Author: Gary Pennington , Daniel Veillard */ #ifndef __XML_GLOBALS_H #define __XML_GLOBALS_H #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif XMLPUBFUN void XMLCALL xmlInitGlobals(void); XMLPUBFUN void XMLCALL xmlCleanupGlobals(void); /** * xmlParserInputBufferCreateFilenameFunc: * @URI: the URI to read from * @enc: the requested source encoding * * Signature for the function doing the lookup for a suitable input method * corresponding to an URI. * * Returns the new xmlParserInputBufferPtr in case of success or NULL if no * method was found. */ typedef xmlParserInputBufferPtr (*xmlParserInputBufferCreateFilenameFunc) (const char *URI, xmlCharEncoding enc); /** * xmlOutputBufferCreateFilenameFunc: * @URI: the URI to write to * @enc: the requested target encoding * * Signature for the function doing the lookup for a suitable output method * corresponding to an URI. * * Returns the new xmlOutputBufferPtr in case of success or NULL if no * method was found. */ typedef xmlOutputBufferPtr (*xmlOutputBufferCreateFilenameFunc) (const char *URI, xmlCharEncodingHandlerPtr encoder, int compression); XMLPUBFUN xmlParserInputBufferCreateFilenameFunc XMLCALL xmlParserInputBufferCreateFilenameDefault (xmlParserInputBufferCreateFilenameFunc func); XMLPUBFUN xmlOutputBufferCreateFilenameFunc XMLCALL xmlOutputBufferCreateFilenameDefault (xmlOutputBufferCreateFilenameFunc func); /* * Externally global symbols which need to be protected for backwards * compatibility support. */ #undef docbDefaultSAXHandler #undef htmlDefaultSAXHandler #undef oldXMLWDcompatibility #undef xmlBufferAllocScheme #undef xmlDefaultBufferSize #undef xmlDefaultSAXHandler #undef xmlDefaultSAXLocator #undef xmlDoValidityCheckingDefaultValue #undef xmlFree #undef xmlGenericError #undef xmlStructuredError #undef xmlGenericErrorContext #undef xmlStructuredErrorContext #undef xmlGetWarningsDefaultValue #undef xmlIndentTreeOutput #undef xmlTreeIndentString #undef xmlKeepBlanksDefaultValue #undef xmlLineNumbersDefaultValue #undef xmlLoadExtDtdDefaultValue #undef xmlMalloc #undef xmlMallocAtomic #undef xmlMemStrdup #undef xmlParserDebugEntities #undef xmlParserVersion #undef xmlPedanticParserDefaultValue #undef xmlRealloc #undef xmlSaveNoEmptyTags #undef xmlSubstituteEntitiesDefaultValue #undef xmlRegisterNodeDefaultValue #undef xmlDeregisterNodeDefaultValue #undef xmlLastError #undef xmlParserInputBufferCreateFilenameValue #undef xmlOutputBufferCreateFilenameValue /** * xmlRegisterNodeFunc: * @node: the current node * * Signature for the registration callback of a created node */ typedef void (*xmlRegisterNodeFunc) (xmlNodePtr node); /** * xmlDeregisterNodeFunc: * @node: the current node * * Signature for the deregistration callback of a discarded node */ typedef void (*xmlDeregisterNodeFunc) (xmlNodePtr node); typedef struct _xmlGlobalState xmlGlobalState; typedef xmlGlobalState *xmlGlobalStatePtr; struct _xmlGlobalState { const char *xmlParserVersion; xmlSAXLocator xmlDefaultSAXLocator; xmlSAXHandlerV1 xmlDefaultSAXHandler; xmlSAXHandlerV1 docbDefaultSAXHandler; xmlSAXHandlerV1 htmlDefaultSAXHandler; xmlFreeFunc xmlFree; xmlMallocFunc xmlMalloc; xmlStrdupFunc xmlMemStrdup; xmlReallocFunc xmlRealloc; xmlGenericErrorFunc xmlGenericError; xmlStructuredErrorFunc xmlStructuredError; void *xmlGenericErrorContext; int oldXMLWDcompatibility; xmlBufferAllocationScheme xmlBufferAllocScheme; int xmlDefaultBufferSize; int xmlSubstituteEntitiesDefaultValue; int xmlDoValidityCheckingDefaultValue; int xmlGetWarningsDefaultValue; int xmlKeepBlanksDefaultValue; int xmlLineNumbersDefaultValue; int xmlLoadExtDtdDefaultValue; int xmlParserDebugEntities; int xmlPedanticParserDefaultValue; int xmlSaveNoEmptyTags; int xmlIndentTreeOutput; const char *xmlTreeIndentString; xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; xmlMallocFunc xmlMallocAtomic; xmlError xmlLastError; xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; void *xmlStructuredErrorContext; }; #ifdef __cplusplus } #endif #include #ifdef __cplusplus extern "C" { #endif XMLPUBFUN void XMLCALL xmlInitializeGlobalState(xmlGlobalStatePtr gs); XMLPUBFUN void XMLCALL xmlThrDefSetGenericErrorFunc(void *ctx, xmlGenericErrorFunc handler); XMLPUBFUN void XMLCALL xmlThrDefSetStructuredErrorFunc(void *ctx, xmlStructuredErrorFunc handler); XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlRegisterNodeDefault(xmlRegisterNodeFunc func); XMLPUBFUN xmlRegisterNodeFunc XMLCALL xmlThrDefRegisterNodeDefault(xmlRegisterNodeFunc func); XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlDeregisterNodeDefault(xmlDeregisterNodeFunc func); XMLPUBFUN xmlDeregisterNodeFunc XMLCALL xmlThrDefDeregisterNodeDefault(xmlDeregisterNodeFunc func); XMLPUBFUN xmlOutputBufferCreateFilenameFunc XMLCALL xmlThrDefOutputBufferCreateFilenameDefault(xmlOutputBufferCreateFilenameFunc func); XMLPUBFUN xmlParserInputBufferCreateFilenameFunc XMLCALL xmlThrDefParserInputBufferCreateFilenameDefault( xmlParserInputBufferCreateFilenameFunc func); /** DOC_DISABLE */ /* * In general the memory allocation entry points are not kept * thread specific but this can be overridden by LIBXML_THREAD_ALLOC_ENABLED * - xmlMalloc * - xmlMallocAtomic * - xmlRealloc * - xmlMemStrdup * - xmlFree */ #ifdef LIBXML_THREAD_ALLOC_ENABLED #ifdef LIBXML_THREAD_ENABLED XMLPUBFUN xmlMallocFunc * XMLCALL __xmlMalloc(void); #define xmlMalloc \ (*(__xmlMalloc())) #else XMLPUBVAR xmlMallocFunc xmlMalloc; #endif #ifdef LIBXML_THREAD_ENABLED XMLPUBFUN xmlMallocFunc * XMLCALL __xmlMallocAtomic(void); #define xmlMallocAtomic \ (*(__xmlMallocAtomic())) #else XMLPUBVAR xmlMallocFunc xmlMallocAtomic; #endif #ifdef LIBXML_THREAD_ENABLED XMLPUBFUN xmlReallocFunc * XMLCALL __xmlRealloc(void); #define xmlRealloc \ (*(__xmlRealloc())) #else XMLPUBVAR xmlReallocFunc xmlRealloc; #endif #ifdef LIBXML_THREAD_ENABLED XMLPUBFUN xmlFreeFunc * XMLCALL __xmlFree(void); #define xmlFree \ (*(__xmlFree())) #else XMLPUBVAR xmlFreeFunc xmlFree; #endif #ifdef LIBXML_THREAD_ENABLED XMLPUBFUN xmlStrdupFunc * XMLCALL __xmlMemStrdup(void); #define xmlMemStrdup \ (*(__xmlMemStrdup())) #else XMLPUBVAR xmlStrdupFunc xmlMemStrdup; #endif #else /* !LIBXML_THREAD_ALLOC_ENABLED */ XMLPUBVAR xmlMallocFunc xmlMalloc; XMLPUBVAR xmlMallocFunc xmlMallocAtomic; XMLPUBVAR xmlReallocFunc xmlRealloc; XMLPUBVAR xmlFreeFunc xmlFree; XMLPUBVAR xmlStrdupFunc xmlMemStrdup; #endif /* LIBXML_THREAD_ALLOC_ENABLED */ #ifdef LIBXML_DOCB_ENABLED XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __docbDefaultSAXHandler(void); #ifdef LIBXML_THREAD_ENABLED #define docbDefaultSAXHandler \ (*(__docbDefaultSAXHandler())) #else XMLPUBVAR xmlSAXHandlerV1 docbDefaultSAXHandler; #endif #endif #ifdef LIBXML_HTML_ENABLED XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __htmlDefaultSAXHandler(void); #ifdef LIBXML_THREAD_ENABLED #define htmlDefaultSAXHandler \ (*(__htmlDefaultSAXHandler())) #else XMLPUBVAR xmlSAXHandlerV1 htmlDefaultSAXHandler; #endif #endif XMLPUBFUN xmlError * XMLCALL __xmlLastError(void); #ifdef LIBXML_THREAD_ENABLED #define xmlLastError \ (*(__xmlLastError())) #else XMLPUBVAR xmlError xmlLastError; #endif /* * Everything starting from the line below is * Automatically generated by build_glob.py. * Do not modify the previous line. */ XMLPUBFUN int * XMLCALL __oldXMLWDcompatibility(void); #ifdef LIBXML_THREAD_ENABLED #define oldXMLWDcompatibility \ (*(__oldXMLWDcompatibility())) #else XMLPUBVAR int oldXMLWDcompatibility; #endif XMLPUBFUN xmlBufferAllocationScheme * XMLCALL __xmlBufferAllocScheme(void); #ifdef LIBXML_THREAD_ENABLED #define xmlBufferAllocScheme \ (*(__xmlBufferAllocScheme())) #else XMLPUBVAR xmlBufferAllocationScheme xmlBufferAllocScheme; #endif XMLPUBFUN xmlBufferAllocationScheme XMLCALL xmlThrDefBufferAllocScheme(xmlBufferAllocationScheme v); XMLPUBFUN int * XMLCALL __xmlDefaultBufferSize(void); #ifdef LIBXML_THREAD_ENABLED #define xmlDefaultBufferSize \ (*(__xmlDefaultBufferSize())) #else XMLPUBVAR int xmlDefaultBufferSize; #endif XMLPUBFUN int XMLCALL xmlThrDefDefaultBufferSize(int v); XMLPUBFUN xmlSAXHandlerV1 * XMLCALL __xmlDefaultSAXHandler(void); #ifdef LIBXML_THREAD_ENABLED #define xmlDefaultSAXHandler \ (*(__xmlDefaultSAXHandler())) #else XMLPUBVAR xmlSAXHandlerV1 xmlDefaultSAXHandler; #endif XMLPUBFUN xmlSAXLocator * XMLCALL __xmlDefaultSAXLocator(void); #ifdef LIBXML_THREAD_ENABLED #define xmlDefaultSAXLocator \ (*(__xmlDefaultSAXLocator())) #else XMLPUBVAR xmlSAXLocator xmlDefaultSAXLocator; #endif XMLPUBFUN int * XMLCALL __xmlDoValidityCheckingDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlDoValidityCheckingDefaultValue \ (*(__xmlDoValidityCheckingDefaultValue())) #else XMLPUBVAR int xmlDoValidityCheckingDefaultValue; #endif XMLPUBFUN int XMLCALL xmlThrDefDoValidityCheckingDefaultValue(int v); XMLPUBFUN xmlGenericErrorFunc * XMLCALL __xmlGenericError(void); #ifdef LIBXML_THREAD_ENABLED #define xmlGenericError \ (*(__xmlGenericError())) #else XMLPUBVAR xmlGenericErrorFunc xmlGenericError; #endif XMLPUBFUN xmlStructuredErrorFunc * XMLCALL __xmlStructuredError(void); #ifdef LIBXML_THREAD_ENABLED #define xmlStructuredError \ (*(__xmlStructuredError())) #else XMLPUBVAR xmlStructuredErrorFunc xmlStructuredError; #endif XMLPUBFUN void * * XMLCALL __xmlGenericErrorContext(void); #ifdef LIBXML_THREAD_ENABLED #define xmlGenericErrorContext \ (*(__xmlGenericErrorContext())) #else XMLPUBVAR void * xmlGenericErrorContext; #endif XMLPUBFUN void * * XMLCALL __xmlStructuredErrorContext(void); #ifdef LIBXML_THREAD_ENABLED #define xmlStructuredErrorContext \ (*(__xmlStructuredErrorContext())) #else XMLPUBVAR void * xmlStructuredErrorContext; #endif XMLPUBFUN int * XMLCALL __xmlGetWarningsDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlGetWarningsDefaultValue \ (*(__xmlGetWarningsDefaultValue())) #else XMLPUBVAR int xmlGetWarningsDefaultValue; #endif XMLPUBFUN int XMLCALL xmlThrDefGetWarningsDefaultValue(int v); XMLPUBFUN int * XMLCALL __xmlIndentTreeOutput(void); #ifdef LIBXML_THREAD_ENABLED #define xmlIndentTreeOutput \ (*(__xmlIndentTreeOutput())) #else XMLPUBVAR int xmlIndentTreeOutput; #endif XMLPUBFUN int XMLCALL xmlThrDefIndentTreeOutput(int v); XMLPUBFUN const char * * XMLCALL __xmlTreeIndentString(void); #ifdef LIBXML_THREAD_ENABLED #define xmlTreeIndentString \ (*(__xmlTreeIndentString())) #else XMLPUBVAR const char * xmlTreeIndentString; #endif XMLPUBFUN const char * XMLCALL xmlThrDefTreeIndentString(const char * v); XMLPUBFUN int * XMLCALL __xmlKeepBlanksDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlKeepBlanksDefaultValue \ (*(__xmlKeepBlanksDefaultValue())) #else XMLPUBVAR int xmlKeepBlanksDefaultValue; #endif XMLPUBFUN int XMLCALL xmlThrDefKeepBlanksDefaultValue(int v); XMLPUBFUN int * XMLCALL __xmlLineNumbersDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlLineNumbersDefaultValue \ (*(__xmlLineNumbersDefaultValue())) #else XMLPUBVAR int xmlLineNumbersDefaultValue; #endif XMLPUBFUN int XMLCALL xmlThrDefLineNumbersDefaultValue(int v); XMLPUBFUN int * XMLCALL __xmlLoadExtDtdDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlLoadExtDtdDefaultValue \ (*(__xmlLoadExtDtdDefaultValue())) #else XMLPUBVAR int xmlLoadExtDtdDefaultValue; #endif XMLPUBFUN int XMLCALL xmlThrDefLoadExtDtdDefaultValue(int v); XMLPUBFUN int * XMLCALL __xmlParserDebugEntities(void); #ifdef LIBXML_THREAD_ENABLED #define xmlParserDebugEntities \ (*(__xmlParserDebugEntities())) #else XMLPUBVAR int xmlParserDebugEntities; #endif XMLPUBFUN int XMLCALL xmlThrDefParserDebugEntities(int v); XMLPUBFUN const char * * XMLCALL __xmlParserVersion(void); #ifdef LIBXML_THREAD_ENABLED #define xmlParserVersion \ (*(__xmlParserVersion())) #else XMLPUBVAR const char * xmlParserVersion; #endif XMLPUBFUN int * XMLCALL __xmlPedanticParserDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlPedanticParserDefaultValue \ (*(__xmlPedanticParserDefaultValue())) #else XMLPUBVAR int xmlPedanticParserDefaultValue; #endif XMLPUBFUN int XMLCALL xmlThrDefPedanticParserDefaultValue(int v); XMLPUBFUN int * XMLCALL __xmlSaveNoEmptyTags(void); #ifdef LIBXML_THREAD_ENABLED #define xmlSaveNoEmptyTags \ (*(__xmlSaveNoEmptyTags())) #else XMLPUBVAR int xmlSaveNoEmptyTags; #endif XMLPUBFUN int XMLCALL xmlThrDefSaveNoEmptyTags(int v); XMLPUBFUN int * XMLCALL __xmlSubstituteEntitiesDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlSubstituteEntitiesDefaultValue \ (*(__xmlSubstituteEntitiesDefaultValue())) #else XMLPUBVAR int xmlSubstituteEntitiesDefaultValue; #endif XMLPUBFUN int XMLCALL xmlThrDefSubstituteEntitiesDefaultValue(int v); XMLPUBFUN xmlRegisterNodeFunc * XMLCALL __xmlRegisterNodeDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlRegisterNodeDefaultValue \ (*(__xmlRegisterNodeDefaultValue())) #else XMLPUBVAR xmlRegisterNodeFunc xmlRegisterNodeDefaultValue; #endif XMLPUBFUN xmlDeregisterNodeFunc * XMLCALL __xmlDeregisterNodeDefaultValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlDeregisterNodeDefaultValue \ (*(__xmlDeregisterNodeDefaultValue())) #else XMLPUBVAR xmlDeregisterNodeFunc xmlDeregisterNodeDefaultValue; #endif XMLPUBFUN xmlParserInputBufferCreateFilenameFunc * XMLCALL \ __xmlParserInputBufferCreateFilenameValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlParserInputBufferCreateFilenameValue \ (*(__xmlParserInputBufferCreateFilenameValue())) #else XMLPUBVAR xmlParserInputBufferCreateFilenameFunc xmlParserInputBufferCreateFilenameValue; #endif XMLPUBFUN xmlOutputBufferCreateFilenameFunc * XMLCALL __xmlOutputBufferCreateFilenameValue(void); #ifdef LIBXML_THREAD_ENABLED #define xmlOutputBufferCreateFilenameValue \ (*(__xmlOutputBufferCreateFilenameValue())) #else XMLPUBVAR xmlOutputBufferCreateFilenameFunc xmlOutputBufferCreateFilenameValue; #endif #ifdef __cplusplus } #endif #endif /* __XML_GLOBALS_H */ PK!W$hhlibxml/entities.hnu[/* * Summary: interface for the XML entities handling * Description: this module provides some of the entity API needed * for the parser and applications. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_ENTITIES_H__ #define __XML_ENTITIES_H__ #include #include #ifdef __cplusplus extern "C" { #endif /* * The different valid entity types. */ typedef enum { XML_INTERNAL_GENERAL_ENTITY = 1, XML_EXTERNAL_GENERAL_PARSED_ENTITY = 2, XML_EXTERNAL_GENERAL_UNPARSED_ENTITY = 3, XML_INTERNAL_PARAMETER_ENTITY = 4, XML_EXTERNAL_PARAMETER_ENTITY = 5, XML_INTERNAL_PREDEFINED_ENTITY = 6 } xmlEntityType; /* * An unit of storage for an entity, contains the string, the value * and the linkind data needed for the linking in the hash table. */ struct _xmlEntity { void *_private; /* application data */ xmlElementType type; /* XML_ENTITY_DECL, must be second ! */ const xmlChar *name; /* Entity name */ struct _xmlNode *children; /* First child link */ struct _xmlNode *last; /* Last child link */ struct _xmlDtd *parent; /* -> DTD */ struct _xmlNode *next; /* next sibling link */ struct _xmlNode *prev; /* previous sibling link */ struct _xmlDoc *doc; /* the containing document */ xmlChar *orig; /* content without ref substitution */ xmlChar *content; /* content or ndata if unparsed */ int length; /* the content length */ xmlEntityType etype; /* The entity type */ const xmlChar *ExternalID; /* External identifier for PUBLIC */ const xmlChar *SystemID; /* URI for a SYSTEM or PUBLIC Entity */ struct _xmlEntity *nexte; /* unused */ const xmlChar *URI; /* the full URI as computed */ int owner; /* does the entity own the childrens */ int checked; /* was the entity content checked */ /* this is also used to count entities * references done from that entity * and if it contains '<' */ }; /* * All entities are stored in an hash table. * There is 2 separate hash tables for global and parameter entities. */ typedef struct _xmlHashTable xmlEntitiesTable; typedef xmlEntitiesTable *xmlEntitiesTablePtr; /* * External functions: */ #ifdef LIBXML_LEGACY_ENABLED XMLPUBFUN void XMLCALL xmlInitializePredefinedEntities (void); #endif /* LIBXML_LEGACY_ENABLED */ XMLPUBFUN xmlEntityPtr XMLCALL xmlNewEntity (xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content); XMLPUBFUN xmlEntityPtr XMLCALL xmlAddDocEntity (xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content); XMLPUBFUN xmlEntityPtr XMLCALL xmlAddDtdEntity (xmlDocPtr doc, const xmlChar *name, int type, const xmlChar *ExternalID, const xmlChar *SystemID, const xmlChar *content); XMLPUBFUN xmlEntityPtr XMLCALL xmlGetPredefinedEntity (const xmlChar *name); XMLPUBFUN xmlEntityPtr XMLCALL xmlGetDocEntity (const xmlDoc *doc, const xmlChar *name); XMLPUBFUN xmlEntityPtr XMLCALL xmlGetDtdEntity (xmlDocPtr doc, const xmlChar *name); XMLPUBFUN xmlEntityPtr XMLCALL xmlGetParameterEntity (xmlDocPtr doc, const xmlChar *name); #ifdef LIBXML_LEGACY_ENABLED XMLPUBFUN const xmlChar * XMLCALL xmlEncodeEntities (xmlDocPtr doc, const xmlChar *input); #endif /* LIBXML_LEGACY_ENABLED */ XMLPUBFUN xmlChar * XMLCALL xmlEncodeEntitiesReentrant(xmlDocPtr doc, const xmlChar *input); XMLPUBFUN xmlChar * XMLCALL xmlEncodeSpecialChars (const xmlDoc *doc, const xmlChar *input); XMLPUBFUN xmlEntitiesTablePtr XMLCALL xmlCreateEntitiesTable (void); #ifdef LIBXML_TREE_ENABLED XMLPUBFUN xmlEntitiesTablePtr XMLCALL xmlCopyEntitiesTable (xmlEntitiesTablePtr table); #endif /* LIBXML_TREE_ENABLED */ XMLPUBFUN void XMLCALL xmlFreeEntitiesTable (xmlEntitiesTablePtr table); #ifdef LIBXML_OUTPUT_ENABLED XMLPUBFUN void XMLCALL xmlDumpEntitiesTable (xmlBufferPtr buf, xmlEntitiesTablePtr table); XMLPUBFUN void XMLCALL xmlDumpEntityDecl (xmlBufferPtr buf, xmlEntityPtr ent); #endif /* LIBXML_OUTPUT_ENABLED */ #ifdef LIBXML_LEGACY_ENABLED XMLPUBFUN void XMLCALL xmlCleanupPredefinedEntities(void); #endif /* LIBXML_LEGACY_ENABLED */ #ifdef __cplusplus } #endif # endif /* __XML_ENTITIES_H__ */ PK! 66libxml/parser.hnu[/* * Summary: the core parser module * Description: Interfaces, constants and types related to the XML parser * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_PARSER_H__ #define __XML_PARSER_H__ #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * XML_DEFAULT_VERSION: * * The default version of XML used: 1.0 */ #define XML_DEFAULT_VERSION "1.0" /** * xmlParserInput: * * An xmlParserInput is an input flow for the XML processor. * Each entity parsed is associated an xmlParserInput (except the * few predefined ones). This is the case both for internal entities * - in which case the flow is already completely in memory - or * external entities - in which case we use the buf structure for * progressive reading and I18N conversions to the internal UTF-8 format. */ /** * xmlParserInputDeallocate: * @str: the string to deallocate * * Callback for freeing some parser input allocations. */ typedef void (* xmlParserInputDeallocate)(xmlChar *str); struct _xmlParserInput { /* Input buffer */ xmlParserInputBufferPtr buf; /* UTF-8 encoded buffer */ const char *filename; /* The file analyzed, if any */ const char *directory; /* the directory/base of the file */ const xmlChar *base; /* Base of the array to parse */ const xmlChar *cur; /* Current char being parsed */ const xmlChar *end; /* end of the array to parse */ int length; /* length if known */ int line; /* Current line */ int col; /* Current column */ /* * NOTE: consumed is only tested for equality in the parser code, * so even if there is an overflow this should not give troubles * for parsing very large instances. */ unsigned long consumed; /* How many xmlChars already consumed */ xmlParserInputDeallocate free; /* function to deallocate the base */ const xmlChar *encoding; /* the encoding string for entity */ const xmlChar *version; /* the version string for entity */ int standalone; /* Was that entity marked standalone */ int id; /* an unique identifier for the entity */ }; /** * xmlParserNodeInfo: * * The parser can be asked to collect Node information, i.e. at what * place in the file they were detected. * NOTE: This is off by default and not very well tested. */ typedef struct _xmlParserNodeInfo xmlParserNodeInfo; typedef xmlParserNodeInfo *xmlParserNodeInfoPtr; struct _xmlParserNodeInfo { const struct _xmlNode* node; /* Position & line # that text that created the node begins & ends on */ unsigned long begin_pos; unsigned long begin_line; unsigned long end_pos; unsigned long end_line; }; typedef struct _xmlParserNodeInfoSeq xmlParserNodeInfoSeq; typedef xmlParserNodeInfoSeq *xmlParserNodeInfoSeqPtr; struct _xmlParserNodeInfoSeq { unsigned long maximum; unsigned long length; xmlParserNodeInfo* buffer; }; /** * xmlParserInputState: * * The parser is now working also as a state based parser. * The recursive one use the state info for entities processing. */ typedef enum { XML_PARSER_EOF = -1, /* nothing is to be parsed */ XML_PARSER_START = 0, /* nothing has been parsed */ XML_PARSER_MISC, /* Misc* before int subset */ XML_PARSER_PI, /* Within a processing instruction */ XML_PARSER_DTD, /* within some DTD content */ XML_PARSER_PROLOG, /* Misc* after internal subset */ XML_PARSER_COMMENT, /* within a comment */ XML_PARSER_START_TAG, /* within a start tag */ XML_PARSER_CONTENT, /* within the content */ XML_PARSER_CDATA_SECTION, /* within a CDATA section */ XML_PARSER_END_TAG, /* within a closing tag */ XML_PARSER_ENTITY_DECL, /* within an entity declaration */ XML_PARSER_ENTITY_VALUE, /* within an entity value in a decl */ XML_PARSER_ATTRIBUTE_VALUE, /* within an attribute value */ XML_PARSER_SYSTEM_LITERAL, /* within a SYSTEM value */ XML_PARSER_EPILOG, /* the Misc* after the last end tag */ XML_PARSER_IGNORE, /* within an IGNORED section */ XML_PARSER_PUBLIC_LITERAL /* within a PUBLIC value */ } xmlParserInputState; /** * XML_DETECT_IDS: * * Bit in the loadsubset context field to tell to do ID/REFs lookups. * Use it to initialize xmlLoadExtDtdDefaultValue. */ #define XML_DETECT_IDS 2 /** * XML_COMPLETE_ATTRS: * * Bit in the loadsubset context field to tell to do complete the * elements attributes lists with the ones defaulted from the DTDs. * Use it to initialize xmlLoadExtDtdDefaultValue. */ #define XML_COMPLETE_ATTRS 4 /** * XML_SKIP_IDS: * * Bit in the loadsubset context field to tell to not do ID/REFs registration. * Used to initialize xmlLoadExtDtdDefaultValue in some special cases. */ #define XML_SKIP_IDS 8 /** * xmlParserMode: * * A parser can operate in various modes */ typedef enum { XML_PARSE_UNKNOWN = 0, XML_PARSE_DOM = 1, XML_PARSE_SAX = 2, XML_PARSE_PUSH_DOM = 3, XML_PARSE_PUSH_SAX = 4, XML_PARSE_READER = 5 } xmlParserMode; typedef struct _xmlStartTag xmlStartTag; /** * xmlParserCtxt: * * The parser context. * NOTE This doesn't completely define the parser state, the (current ?) * design of the parser uses recursive function calls since this allow * and easy mapping from the production rules of the specification * to the actual code. The drawback is that the actual function call * also reflect the parser state. However most of the parsing routines * takes as the only argument the parser context pointer, so migrating * to a state based parser for progressive parsing shouldn't be too hard. */ struct _xmlParserCtxt { struct _xmlSAXHandler *sax; /* The SAX handler */ void *userData; /* For SAX interface only, used by DOM build */ xmlDocPtr myDoc; /* the document being built */ int wellFormed; /* is the document well formed */ int replaceEntities; /* shall we replace entities ? */ const xmlChar *version; /* the XML version string */ const xmlChar *encoding; /* the declared encoding, if any */ int standalone; /* standalone document */ int html; /* an HTML(1)/Docbook(2) document * 3 is HTML after * 10 is HTML after */ /* Input stream stack */ xmlParserInputPtr input; /* Current input stream */ int inputNr; /* Number of current input streams */ int inputMax; /* Max number of input streams */ xmlParserInputPtr *inputTab; /* stack of inputs */ /* Node analysis stack only used for DOM building */ xmlNodePtr node; /* Current parsed Node */ int nodeNr; /* Depth of the parsing stack */ int nodeMax; /* Max depth of the parsing stack */ xmlNodePtr *nodeTab; /* array of nodes */ int record_info; /* Whether node info should be kept */ xmlParserNodeInfoSeq node_seq; /* info about each node parsed */ int errNo; /* error code */ int hasExternalSubset; /* reference and external subset */ int hasPErefs; /* the internal subset has PE refs */ int external; /* are we parsing an external entity */ int valid; /* is the document valid */ int validate; /* shall we try to validate ? */ xmlValidCtxt vctxt; /* The validity context */ xmlParserInputState instate; /* current type of input */ int token; /* next char look-ahead */ char *directory; /* the data directory */ /* Node name stack */ const xmlChar *name; /* Current parsed Node */ int nameNr; /* Depth of the parsing stack */ int nameMax; /* Max depth of the parsing stack */ const xmlChar * *nameTab; /* array of nodes */ long nbChars; /* unused */ long checkIndex; /* used by progressive parsing lookup */ int keepBlanks; /* ugly but ... */ int disableSAX; /* SAX callbacks are disabled */ int inSubset; /* Parsing is in int 1/ext 2 subset */ const xmlChar * intSubName; /* name of subset */ xmlChar * extSubURI; /* URI of external subset */ xmlChar * extSubSystem; /* SYSTEM ID of external subset */ /* xml:space values */ int * space; /* Should the parser preserve spaces */ int spaceNr; /* Depth of the parsing stack */ int spaceMax; /* Max depth of the parsing stack */ int * spaceTab; /* array of space infos */ int depth; /* to prevent entity substitution loops */ xmlParserInputPtr entity; /* used to check entities boundaries */ int charset; /* encoding of the in-memory content actually an xmlCharEncoding */ int nodelen; /* Those two fields are there to */ int nodemem; /* Speed up large node parsing */ int pedantic; /* signal pedantic warnings */ void *_private; /* For user data, libxml won't touch it */ int loadsubset; /* should the external subset be loaded */ int linenumbers; /* set line number in element content */ void *catalogs; /* document's own catalog */ int recovery; /* run in recovery mode */ int progressive; /* is this a progressive parsing */ xmlDictPtr dict; /* dictionary for the parser */ const xmlChar * *atts; /* array for the attributes callbacks */ int maxatts; /* the size of the array */ int docdict; /* use strings from dict to build tree */ /* * pre-interned strings */ const xmlChar *str_xml; const xmlChar *str_xmlns; const xmlChar *str_xml_ns; /* * Everything below is used only by the new SAX mode */ int sax2; /* operating in the new SAX mode */ int nsNr; /* the number of inherited namespaces */ int nsMax; /* the size of the arrays */ const xmlChar * *nsTab; /* the array of prefix/namespace name */ int *attallocs; /* which attribute were allocated */ xmlStartTag *pushTab; /* array of data for push */ xmlHashTablePtr attsDefault; /* defaulted attributes if any */ xmlHashTablePtr attsSpecial; /* non-CDATA attributes if any */ int nsWellFormed; /* is the document XML Namespace okay */ int options; /* Extra options */ /* * Those fields are needed only for streaming parsing so far */ int dictNames; /* Use dictionary names for the tree */ int freeElemsNr; /* number of freed element nodes */ xmlNodePtr freeElems; /* List of freed element nodes */ int freeAttrsNr; /* number of freed attributes nodes */ xmlAttrPtr freeAttrs; /* List of freed attributes nodes */ /* * the complete error information for the last error. */ xmlError lastError; xmlParserMode parseMode; /* the parser mode */ unsigned long nbentities; /* number of entities references */ unsigned long sizeentities; /* size of parsed entities */ /* for use by HTML non-recursive parser */ xmlParserNodeInfo *nodeInfo; /* Current NodeInfo */ int nodeInfoNr; /* Depth of the parsing stack */ int nodeInfoMax; /* Max depth of the parsing stack */ xmlParserNodeInfo *nodeInfoTab; /* array of nodeInfos */ int input_id; /* we need to label inputs */ unsigned long sizeentcopy; /* volume of entity copy */ }; /** * xmlSAXLocator: * * A SAX Locator. */ struct _xmlSAXLocator { const xmlChar *(*getPublicId)(void *ctx); const xmlChar *(*getSystemId)(void *ctx); int (*getLineNumber)(void *ctx); int (*getColumnNumber)(void *ctx); }; /** * xmlSAXHandler: * * A SAX handler is bunch of callbacks called by the parser when processing * of the input generate data or structure information. */ /** * resolveEntitySAXFunc: * @ctx: the user data (XML parser context) * @publicId: The public ID of the entity * @systemId: The system ID of the entity * * Callback: * The entity loader, to control the loading of external entities, * the application can either: * - override this resolveEntity() callback in the SAX block * - or better use the xmlSetExternalEntityLoader() function to * set up it's own entity resolution routine * * Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour. */ typedef xmlParserInputPtr (*resolveEntitySAXFunc) (void *ctx, const xmlChar *publicId, const xmlChar *systemId); /** * internalSubsetSAXFunc: * @ctx: the user data (XML parser context) * @name: the root element name * @ExternalID: the external ID * @SystemID: the SYSTEM ID (e.g. filename or URL) * * Callback on internal subset declaration. */ typedef void (*internalSubsetSAXFunc) (void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); /** * externalSubsetSAXFunc: * @ctx: the user data (XML parser context) * @name: the root element name * @ExternalID: the external ID * @SystemID: the SYSTEM ID (e.g. filename or URL) * * Callback on external subset declaration. */ typedef void (*externalSubsetSAXFunc) (void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); /** * getEntitySAXFunc: * @ctx: the user data (XML parser context) * @name: The entity name * * Get an entity by name. * * Returns the xmlEntityPtr if found. */ typedef xmlEntityPtr (*getEntitySAXFunc) (void *ctx, const xmlChar *name); /** * getParameterEntitySAXFunc: * @ctx: the user data (XML parser context) * @name: The entity name * * Get a parameter entity by name. * * Returns the xmlEntityPtr if found. */ typedef xmlEntityPtr (*getParameterEntitySAXFunc) (void *ctx, const xmlChar *name); /** * entityDeclSAXFunc: * @ctx: the user data (XML parser context) * @name: the entity name * @type: the entity type * @publicId: The public ID of the entity * @systemId: The system ID of the entity * @content: the entity value (without processing). * * An entity definition has been parsed. */ typedef void (*entityDeclSAXFunc) (void *ctx, const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content); /** * notationDeclSAXFunc: * @ctx: the user data (XML parser context) * @name: The name of the notation * @publicId: The public ID of the entity * @systemId: The system ID of the entity * * What to do when a notation declaration has been parsed. */ typedef void (*notationDeclSAXFunc)(void *ctx, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId); /** * attributeDeclSAXFunc: * @ctx: the user data (XML parser context) * @elem: the name of the element * @fullname: the attribute name * @type: the attribute type * @def: the type of default value * @defaultValue: the attribute default value * @tree: the tree of enumerated value set * * An attribute definition has been parsed. */ typedef void (*attributeDeclSAXFunc)(void *ctx, const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree); /** * elementDeclSAXFunc: * @ctx: the user data (XML parser context) * @name: the element name * @type: the element type * @content: the element value tree * * An element definition has been parsed. */ typedef void (*elementDeclSAXFunc)(void *ctx, const xmlChar *name, int type, xmlElementContentPtr content); /** * unparsedEntityDeclSAXFunc: * @ctx: the user data (XML parser context) * @name: The name of the entity * @publicId: The public ID of the entity * @systemId: The system ID of the entity * @notationName: the name of the notation * * What to do when an unparsed entity declaration is parsed. */ typedef void (*unparsedEntityDeclSAXFunc)(void *ctx, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName); /** * setDocumentLocatorSAXFunc: * @ctx: the user data (XML parser context) * @loc: A SAX Locator * * Receive the document locator at startup, actually xmlDefaultSAXLocator. * Everything is available on the context, so this is useless in our case. */ typedef void (*setDocumentLocatorSAXFunc) (void *ctx, xmlSAXLocatorPtr loc); /** * startDocumentSAXFunc: * @ctx: the user data (XML parser context) * * Called when the document start being processed. */ typedef void (*startDocumentSAXFunc) (void *ctx); /** * endDocumentSAXFunc: * @ctx: the user data (XML parser context) * * Called when the document end has been detected. */ typedef void (*endDocumentSAXFunc) (void *ctx); /** * startElementSAXFunc: * @ctx: the user data (XML parser context) * @name: The element name, including namespace prefix * @atts: An array of name/value attributes pairs, NULL terminated * * Called when an opening tag has been processed. */ typedef void (*startElementSAXFunc) (void *ctx, const xmlChar *name, const xmlChar **atts); /** * endElementSAXFunc: * @ctx: the user data (XML parser context) * @name: The element name * * Called when the end of an element has been detected. */ typedef void (*endElementSAXFunc) (void *ctx, const xmlChar *name); /** * attributeSAXFunc: * @ctx: the user data (XML parser context) * @name: The attribute name, including namespace prefix * @value: The attribute value * * Handle an attribute that has been read by the parser. * The default handling is to convert the attribute into an * DOM subtree and past it in a new xmlAttr element added to * the element. */ typedef void (*attributeSAXFunc) (void *ctx, const xmlChar *name, const xmlChar *value); /** * referenceSAXFunc: * @ctx: the user data (XML parser context) * @name: The entity name * * Called when an entity reference is detected. */ typedef void (*referenceSAXFunc) (void *ctx, const xmlChar *name); /** * charactersSAXFunc: * @ctx: the user data (XML parser context) * @ch: a xmlChar string * @len: the number of xmlChar * * Receiving some chars from the parser. */ typedef void (*charactersSAXFunc) (void *ctx, const xmlChar *ch, int len); /** * ignorableWhitespaceSAXFunc: * @ctx: the user data (XML parser context) * @ch: a xmlChar string * @len: the number of xmlChar * * Receiving some ignorable whitespaces from the parser. * UNUSED: by default the DOM building will use characters. */ typedef void (*ignorableWhitespaceSAXFunc) (void *ctx, const xmlChar *ch, int len); /** * processingInstructionSAXFunc: * @ctx: the user data (XML parser context) * @target: the target name * @data: the PI data's * * A processing instruction has been parsed. */ typedef void (*processingInstructionSAXFunc) (void *ctx, const xmlChar *target, const xmlChar *data); /** * commentSAXFunc: * @ctx: the user data (XML parser context) * @value: the comment content * * A comment has been parsed. */ typedef void (*commentSAXFunc) (void *ctx, const xmlChar *value); /** * cdataBlockSAXFunc: * @ctx: the user data (XML parser context) * @value: The pcdata content * @len: the block length * * Called when a pcdata block has been parsed. */ typedef void (*cdataBlockSAXFunc) ( void *ctx, const xmlChar *value, int len); /** * warningSAXFunc: * @ctx: an XML parser context * @msg: the message to display/transmit * @...: extra parameters for the message display * * Display and format a warning messages, callback. */ typedef void (XMLCDECL *warningSAXFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * errorSAXFunc: * @ctx: an XML parser context * @msg: the message to display/transmit * @...: extra parameters for the message display * * Display and format an error messages, callback. */ typedef void (XMLCDECL *errorSAXFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * fatalErrorSAXFunc: * @ctx: an XML parser context * @msg: the message to display/transmit * @...: extra parameters for the message display * * Display and format fatal error messages, callback. * Note: so far fatalError() SAX callbacks are not used, error() * get all the callbacks for errors. */ typedef void (XMLCDECL *fatalErrorSAXFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * isStandaloneSAXFunc: * @ctx: the user data (XML parser context) * * Is this document tagged standalone? * * Returns 1 if true */ typedef int (*isStandaloneSAXFunc) (void *ctx); /** * hasInternalSubsetSAXFunc: * @ctx: the user data (XML parser context) * * Does this document has an internal subset. * * Returns 1 if true */ typedef int (*hasInternalSubsetSAXFunc) (void *ctx); /** * hasExternalSubsetSAXFunc: * @ctx: the user data (XML parser context) * * Does this document has an external subset? * * Returns 1 if true */ typedef int (*hasExternalSubsetSAXFunc) (void *ctx); /************************************************************************ * * * The SAX version 2 API extensions * * * ************************************************************************/ /** * XML_SAX2_MAGIC: * * Special constant found in SAX2 blocks initialized fields */ #define XML_SAX2_MAGIC 0xDEEDBEAF /** * startElementNsSAX2Func: * @ctx: the user data (XML parser context) * @localname: the local name of the element * @prefix: the element namespace prefix if available * @URI: the element namespace name if available * @nb_namespaces: number of namespace definitions on that node * @namespaces: pointer to the array of prefix/URI pairs namespace definitions * @nb_attributes: the number of attributes on that node * @nb_defaulted: the number of defaulted attributes. The defaulted * ones are at the end of the array * @attributes: pointer to the array of (localname/prefix/URI/value/end) * attribute values. * * SAX2 callback when an element start has been detected by the parser. * It provides the namespace information for the element, as well as * the new namespace declarations on the element. */ typedef void (*startElementNsSAX2Func) (void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI, int nb_namespaces, const xmlChar **namespaces, int nb_attributes, int nb_defaulted, const xmlChar **attributes); /** * endElementNsSAX2Func: * @ctx: the user data (XML parser context) * @localname: the local name of the element * @prefix: the element namespace prefix if available * @URI: the element namespace name if available * * SAX2 callback when an element end has been detected by the parser. * It provides the namespace information for the element. */ typedef void (*endElementNsSAX2Func) (void *ctx, const xmlChar *localname, const xmlChar *prefix, const xmlChar *URI); struct _xmlSAXHandler { internalSubsetSAXFunc internalSubset; isStandaloneSAXFunc isStandalone; hasInternalSubsetSAXFunc hasInternalSubset; hasExternalSubsetSAXFunc hasExternalSubset; resolveEntitySAXFunc resolveEntity; getEntitySAXFunc getEntity; entityDeclSAXFunc entityDecl; notationDeclSAXFunc notationDecl; attributeDeclSAXFunc attributeDecl; elementDeclSAXFunc elementDecl; unparsedEntityDeclSAXFunc unparsedEntityDecl; setDocumentLocatorSAXFunc setDocumentLocator; startDocumentSAXFunc startDocument; endDocumentSAXFunc endDocument; startElementSAXFunc startElement; endElementSAXFunc endElement; referenceSAXFunc reference; charactersSAXFunc characters; ignorableWhitespaceSAXFunc ignorableWhitespace; processingInstructionSAXFunc processingInstruction; commentSAXFunc comment; warningSAXFunc warning; errorSAXFunc error; fatalErrorSAXFunc fatalError; /* unused error() get all the errors */ getParameterEntitySAXFunc getParameterEntity; cdataBlockSAXFunc cdataBlock; externalSubsetSAXFunc externalSubset; unsigned int initialized; /* The following fields are extensions available only on version 2 */ void *_private; startElementNsSAX2Func startElementNs; endElementNsSAX2Func endElementNs; xmlStructuredErrorFunc serror; }; /* * SAX Version 1 */ typedef struct _xmlSAXHandlerV1 xmlSAXHandlerV1; typedef xmlSAXHandlerV1 *xmlSAXHandlerV1Ptr; struct _xmlSAXHandlerV1 { internalSubsetSAXFunc internalSubset; isStandaloneSAXFunc isStandalone; hasInternalSubsetSAXFunc hasInternalSubset; hasExternalSubsetSAXFunc hasExternalSubset; resolveEntitySAXFunc resolveEntity; getEntitySAXFunc getEntity; entityDeclSAXFunc entityDecl; notationDeclSAXFunc notationDecl; attributeDeclSAXFunc attributeDecl; elementDeclSAXFunc elementDecl; unparsedEntityDeclSAXFunc unparsedEntityDecl; setDocumentLocatorSAXFunc setDocumentLocator; startDocumentSAXFunc startDocument; endDocumentSAXFunc endDocument; startElementSAXFunc startElement; endElementSAXFunc endElement; referenceSAXFunc reference; charactersSAXFunc characters; ignorableWhitespaceSAXFunc ignorableWhitespace; processingInstructionSAXFunc processingInstruction; commentSAXFunc comment; warningSAXFunc warning; errorSAXFunc error; fatalErrorSAXFunc fatalError; /* unused error() get all the errors */ getParameterEntitySAXFunc getParameterEntity; cdataBlockSAXFunc cdataBlock; externalSubsetSAXFunc externalSubset; unsigned int initialized; }; /** * xmlExternalEntityLoader: * @URL: The System ID of the resource requested * @ID: The Public ID of the resource requested * @context: the XML parser context * * External entity loaders types. * * Returns the entity input parser. */ typedef xmlParserInputPtr (*xmlExternalEntityLoader) (const char *URL, const char *ID, xmlParserCtxtPtr context); #ifdef __cplusplus } #endif #include #include #include #ifdef __cplusplus extern "C" { #endif /* * Init/Cleanup */ XMLPUBFUN void XMLCALL xmlInitParser (void); XMLPUBFUN void XMLCALL xmlCleanupParser (void); /* * Input functions */ XMLPUBFUN int XMLCALL xmlParserInputRead (xmlParserInputPtr in, int len); XMLPUBFUN int XMLCALL xmlParserInputGrow (xmlParserInputPtr in, int len); /* * Basic parsing Interfaces */ #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN xmlDocPtr XMLCALL xmlParseDoc (const xmlChar *cur); XMLPUBFUN xmlDocPtr XMLCALL xmlParseFile (const char *filename); XMLPUBFUN xmlDocPtr XMLCALL xmlParseMemory (const char *buffer, int size); #endif /* LIBXML_SAX1_ENABLED */ XMLPUBFUN int XMLCALL xmlSubstituteEntitiesDefault(int val); XMLPUBFUN int XMLCALL xmlKeepBlanksDefault (int val); XMLPUBFUN void XMLCALL xmlStopParser (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlPedanticParserDefault(int val); XMLPUBFUN int XMLCALL xmlLineNumbersDefault (int val); #ifdef LIBXML_SAX1_ENABLED /* * Recovery mode */ XMLPUBFUN xmlDocPtr XMLCALL xmlRecoverDoc (const xmlChar *cur); XMLPUBFUN xmlDocPtr XMLCALL xmlRecoverMemory (const char *buffer, int size); XMLPUBFUN xmlDocPtr XMLCALL xmlRecoverFile (const char *filename); #endif /* LIBXML_SAX1_ENABLED */ /* * Less common routines and SAX interfaces */ XMLPUBFUN int XMLCALL xmlParseDocument (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlParseExtParsedEnt (xmlParserCtxtPtr ctxt); #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN int XMLCALL xmlSAXUserParseFile (xmlSAXHandlerPtr sax, void *user_data, const char *filename); XMLPUBFUN int XMLCALL xmlSAXUserParseMemory (xmlSAXHandlerPtr sax, void *user_data, const char *buffer, int size); XMLPUBFUN xmlDocPtr XMLCALL xmlSAXParseDoc (xmlSAXHandlerPtr sax, const xmlChar *cur, int recovery); XMLPUBFUN xmlDocPtr XMLCALL xmlSAXParseMemory (xmlSAXHandlerPtr sax, const char *buffer, int size, int recovery); XMLPUBFUN xmlDocPtr XMLCALL xmlSAXParseMemoryWithData (xmlSAXHandlerPtr sax, const char *buffer, int size, int recovery, void *data); XMLPUBFUN xmlDocPtr XMLCALL xmlSAXParseFile (xmlSAXHandlerPtr sax, const char *filename, int recovery); XMLPUBFUN xmlDocPtr XMLCALL xmlSAXParseFileWithData (xmlSAXHandlerPtr sax, const char *filename, int recovery, void *data); XMLPUBFUN xmlDocPtr XMLCALL xmlSAXParseEntity (xmlSAXHandlerPtr sax, const char *filename); XMLPUBFUN xmlDocPtr XMLCALL xmlParseEntity (const char *filename); #endif /* LIBXML_SAX1_ENABLED */ #ifdef LIBXML_VALID_ENABLED XMLPUBFUN xmlDtdPtr XMLCALL xmlSAXParseDTD (xmlSAXHandlerPtr sax, const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN xmlDtdPtr XMLCALL xmlParseDTD (const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN xmlDtdPtr XMLCALL xmlIOParseDTD (xmlSAXHandlerPtr sax, xmlParserInputBufferPtr input, xmlCharEncoding enc); #endif /* LIBXML_VALID_ENABLE */ #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN int XMLCALL xmlParseBalancedChunkMemory(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst); #endif /* LIBXML_SAX1_ENABLED */ XMLPUBFUN xmlParserErrors XMLCALL xmlParseInNodeContext (xmlNodePtr node, const char *data, int datalen, int options, xmlNodePtr *lst); #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN int XMLCALL xmlParseBalancedChunkMemoryRecover(xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data, int depth, const xmlChar *string, xmlNodePtr *lst, int recover); XMLPUBFUN int XMLCALL xmlParseExternalEntity (xmlDocPtr doc, xmlSAXHandlerPtr sax, void *user_data, int depth, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst); #endif /* LIBXML_SAX1_ENABLED */ XMLPUBFUN int XMLCALL xmlParseCtxtExternalEntity(xmlParserCtxtPtr ctx, const xmlChar *URL, const xmlChar *ID, xmlNodePtr *lst); /* * Parser contexts handling. */ XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlNewParserCtxt (void); XMLPUBFUN int XMLCALL xmlInitParserCtxt (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlClearParserCtxt (xmlParserCtxtPtr ctxt); XMLPUBFUN void XMLCALL xmlFreeParserCtxt (xmlParserCtxtPtr ctxt); #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN void XMLCALL xmlSetupParserForBuffer (xmlParserCtxtPtr ctxt, const xmlChar* buffer, const char *filename); #endif /* LIBXML_SAX1_ENABLED */ XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlCreateDocParserCtxt (const xmlChar *cur); #ifdef LIBXML_LEGACY_ENABLED /* * Reading/setting optional parsing features. */ XMLPUBFUN int XMLCALL xmlGetFeaturesList (int *len, const char **result); XMLPUBFUN int XMLCALL xmlGetFeature (xmlParserCtxtPtr ctxt, const char *name, void *result); XMLPUBFUN int XMLCALL xmlSetFeature (xmlParserCtxtPtr ctxt, const char *name, void *value); #endif /* LIBXML_LEGACY_ENABLED */ #ifdef LIBXML_PUSH_ENABLED /* * Interfaces for the Push mode. */ XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlCreatePushParserCtxt(xmlSAXHandlerPtr sax, void *user_data, const char *chunk, int size, const char *filename); XMLPUBFUN int XMLCALL xmlParseChunk (xmlParserCtxtPtr ctxt, const char *chunk, int size, int terminate); #endif /* LIBXML_PUSH_ENABLED */ /* * Special I/O mode. */ XMLPUBFUN xmlParserCtxtPtr XMLCALL xmlCreateIOParserCtxt (xmlSAXHandlerPtr sax, void *user_data, xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, xmlCharEncoding enc); XMLPUBFUN xmlParserInputPtr XMLCALL xmlNewIOInputStream (xmlParserCtxtPtr ctxt, xmlParserInputBufferPtr input, xmlCharEncoding enc); /* * Node infos. */ XMLPUBFUN const xmlParserNodeInfo* XMLCALL xmlParserFindNodeInfo (const xmlParserCtxtPtr ctxt, const xmlNodePtr node); XMLPUBFUN void XMLCALL xmlInitNodeInfoSeq (xmlParserNodeInfoSeqPtr seq); XMLPUBFUN void XMLCALL xmlClearNodeInfoSeq (xmlParserNodeInfoSeqPtr seq); XMLPUBFUN unsigned long XMLCALL xmlParserFindNodeInfoIndex(const xmlParserNodeInfoSeqPtr seq, const xmlNodePtr node); XMLPUBFUN void XMLCALL xmlParserAddNodeInfo (xmlParserCtxtPtr ctxt, const xmlParserNodeInfoPtr info); /* * External entities handling actually implemented in xmlIO. */ XMLPUBFUN void XMLCALL xmlSetExternalEntityLoader(xmlExternalEntityLoader f); XMLPUBFUN xmlExternalEntityLoader XMLCALL xmlGetExternalEntityLoader(void); XMLPUBFUN xmlParserInputPtr XMLCALL xmlLoadExternalEntity (const char *URL, const char *ID, xmlParserCtxtPtr ctxt); /* * Index lookup, actually implemented in the encoding module */ XMLPUBFUN long XMLCALL xmlByteConsumed (xmlParserCtxtPtr ctxt); /* * New set of simpler/more flexible APIs */ /** * xmlParserOption: * * This is the set of XML parser options that can be passed down * to the xmlReadDoc() and similar calls. */ typedef enum { XML_PARSE_RECOVER = 1<<0, /* recover on errors */ XML_PARSE_NOENT = 1<<1, /* substitute entities */ XML_PARSE_DTDLOAD = 1<<2, /* load the external subset */ XML_PARSE_DTDATTR = 1<<3, /* default DTD attributes */ XML_PARSE_DTDVALID = 1<<4, /* validate with the DTD */ XML_PARSE_NOERROR = 1<<5, /* suppress error reports */ XML_PARSE_NOWARNING = 1<<6, /* suppress warning reports */ XML_PARSE_PEDANTIC = 1<<7, /* pedantic error reporting */ XML_PARSE_NOBLANKS = 1<<8, /* remove blank nodes */ XML_PARSE_SAX1 = 1<<9, /* use the SAX1 interface internally */ XML_PARSE_XINCLUDE = 1<<10,/* Implement XInclude substitution */ XML_PARSE_NONET = 1<<11,/* Forbid network access */ XML_PARSE_NODICT = 1<<12,/* Do not reuse the context dictionary */ XML_PARSE_NSCLEAN = 1<<13,/* remove redundant namespaces declarations */ XML_PARSE_NOCDATA = 1<<14,/* merge CDATA as text nodes */ XML_PARSE_NOXINCNODE= 1<<15,/* do not generate XINCLUDE START/END nodes */ XML_PARSE_COMPACT = 1<<16,/* compact small text nodes; no modification of the tree allowed afterwards (will possibly crash if you try to modify the tree) */ XML_PARSE_OLD10 = 1<<17,/* parse using XML-1.0 before update 5 */ XML_PARSE_NOBASEFIX = 1<<18,/* do not fixup XINCLUDE xml:base uris */ XML_PARSE_HUGE = 1<<19,/* relax any hardcoded limit from the parser */ XML_PARSE_OLDSAX = 1<<20,/* parse using SAX2 interface before 2.7.0 */ XML_PARSE_IGNORE_ENC= 1<<21,/* ignore internal document encoding hint */ XML_PARSE_BIG_LINES = 1<<22 /* Store big lines numbers in text PSVI field */ } xmlParserOption; XMLPUBFUN void XMLCALL xmlCtxtReset (xmlParserCtxtPtr ctxt); XMLPUBFUN int XMLCALL xmlCtxtResetPush (xmlParserCtxtPtr ctxt, const char *chunk, int size, const char *filename, const char *encoding); XMLPUBFUN int XMLCALL xmlCtxtUseOptions (xmlParserCtxtPtr ctxt, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlReadDoc (const xmlChar *cur, const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlReadFile (const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlReadMemory (const char *buffer, int size, const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlReadFd (int fd, const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlReadIO (xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlCtxtReadDoc (xmlParserCtxtPtr ctxt, const xmlChar *cur, const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlCtxtReadFile (xmlParserCtxtPtr ctxt, const char *filename, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlCtxtReadMemory (xmlParserCtxtPtr ctxt, const char *buffer, int size, const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlCtxtReadFd (xmlParserCtxtPtr ctxt, int fd, const char *URL, const char *encoding, int options); XMLPUBFUN xmlDocPtr XMLCALL xmlCtxtReadIO (xmlParserCtxtPtr ctxt, xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void *ioctx, const char *URL, const char *encoding, int options); /* * Library wide options */ /** * xmlFeature: * * Used to examine the existence of features that can be enabled * or disabled at compile-time. * They used to be called XML_FEATURE_xxx but this clashed with Expat */ typedef enum { XML_WITH_THREAD = 1, XML_WITH_TREE = 2, XML_WITH_OUTPUT = 3, XML_WITH_PUSH = 4, XML_WITH_READER = 5, XML_WITH_PATTERN = 6, XML_WITH_WRITER = 7, XML_WITH_SAX1 = 8, XML_WITH_FTP = 9, XML_WITH_HTTP = 10, XML_WITH_VALID = 11, XML_WITH_HTML = 12, XML_WITH_LEGACY = 13, XML_WITH_C14N = 14, XML_WITH_CATALOG = 15, XML_WITH_XPATH = 16, XML_WITH_XPTR = 17, XML_WITH_XINCLUDE = 18, XML_WITH_ICONV = 19, XML_WITH_ISO8859X = 20, XML_WITH_UNICODE = 21, XML_WITH_REGEXP = 22, XML_WITH_AUTOMATA = 23, XML_WITH_EXPR = 24, XML_WITH_SCHEMAS = 25, XML_WITH_SCHEMATRON = 26, XML_WITH_MODULES = 27, XML_WITH_DEBUG = 28, XML_WITH_DEBUG_MEM = 29, XML_WITH_DEBUG_RUN = 30, XML_WITH_ZLIB = 31, XML_WITH_ICU = 32, XML_WITH_LZMA = 33, XML_WITH_NONE = 99999 /* just to be sure of allocation size */ } xmlFeature; XMLPUBFUN int XMLCALL xmlHasFeature (xmlFeature feature); #ifdef __cplusplus } #endif #endif /* __XML_PARSER_H__ */ PK!l:99libxml/xmlmemory.hnu[/* * Summary: interface for the memory allocator * Description: provides interfaces for the memory allocator, * including debugging capabilities. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __DEBUG_MEMORY_ALLOC__ #define __DEBUG_MEMORY_ALLOC__ #include #include /** * DEBUG_MEMORY: * * DEBUG_MEMORY replaces the allocator with a collect and debug * shell to the libc allocator. * DEBUG_MEMORY should only be activated when debugging * libxml i.e. if libxml has been configured with --with-debug-mem too. */ /* #define DEBUG_MEMORY_FREED */ /* #define DEBUG_MEMORY_LOCATION */ #ifdef DEBUG #ifndef DEBUG_MEMORY #define DEBUG_MEMORY #endif #endif /** * DEBUG_MEMORY_LOCATION: * * DEBUG_MEMORY_LOCATION should be activated only when debugging * libxml i.e. if libxml has been configured with --with-debug-mem too. */ #ifdef DEBUG_MEMORY_LOCATION #endif #ifdef __cplusplus extern "C" { #endif /* * The XML memory wrapper support 4 basic overloadable functions. */ /** * xmlFreeFunc: * @mem: an already allocated block of memory * * Signature for a free() implementation. */ typedef void (XMLCALL *xmlFreeFunc)(void *mem); /** * xmlMallocFunc: * @size: the size requested in bytes * * Signature for a malloc() implementation. * * Returns a pointer to the newly allocated block or NULL in case of error. */ typedef void *(LIBXML_ATTR_ALLOC_SIZE(1) XMLCALL *xmlMallocFunc)(size_t size); /** * xmlReallocFunc: * @mem: an already allocated block of memory * @size: the new size requested in bytes * * Signature for a realloc() implementation. * * Returns a pointer to the newly reallocated block or NULL in case of error. */ typedef void *(XMLCALL *xmlReallocFunc)(void *mem, size_t size); /** * xmlStrdupFunc: * @str: a zero terminated string * * Signature for an strdup() implementation. * * Returns the copy of the string or NULL in case of error. */ typedef char *(XMLCALL *xmlStrdupFunc)(const char *str); /* * The 4 interfaces used for all memory handling within libxml. LIBXML_DLL_IMPORT xmlFreeFunc xmlFree; LIBXML_DLL_IMPORT xmlMallocFunc xmlMalloc; LIBXML_DLL_IMPORT xmlMallocFunc xmlMallocAtomic; LIBXML_DLL_IMPORT xmlReallocFunc xmlRealloc; LIBXML_DLL_IMPORT xmlStrdupFunc xmlMemStrdup; */ /* * The way to overload the existing functions. * The xmlGc function have an extra entry for atomic block * allocations useful for garbage collected memory allocators */ XMLPUBFUN int XMLCALL xmlMemSetup (xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc); XMLPUBFUN int XMLCALL xmlMemGet (xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc); XMLPUBFUN int XMLCALL xmlGcMemSetup (xmlFreeFunc freeFunc, xmlMallocFunc mallocFunc, xmlMallocFunc mallocAtomicFunc, xmlReallocFunc reallocFunc, xmlStrdupFunc strdupFunc); XMLPUBFUN int XMLCALL xmlGcMemGet (xmlFreeFunc *freeFunc, xmlMallocFunc *mallocFunc, xmlMallocFunc *mallocAtomicFunc, xmlReallocFunc *reallocFunc, xmlStrdupFunc *strdupFunc); /* * Initialization of the memory layer. */ XMLPUBFUN int XMLCALL xmlInitMemory (void); /* * Cleanup of the memory layer. */ XMLPUBFUN void XMLCALL xmlCleanupMemory (void); /* * These are specific to the XML debug memory wrapper. */ XMLPUBFUN int XMLCALL xmlMemUsed (void); XMLPUBFUN int XMLCALL xmlMemBlocks (void); XMLPUBFUN void XMLCALL xmlMemDisplay (FILE *fp); XMLPUBFUN void XMLCALL xmlMemDisplayLast(FILE *fp, long nbBytes); XMLPUBFUN void XMLCALL xmlMemShow (FILE *fp, int nr); XMLPUBFUN void XMLCALL xmlMemoryDump (void); XMLPUBFUN void * XMLCALL xmlMemMalloc (size_t size) LIBXML_ATTR_ALLOC_SIZE(1); XMLPUBFUN void * XMLCALL xmlMemRealloc (void *ptr,size_t size); XMLPUBFUN void XMLCALL xmlMemFree (void *ptr); XMLPUBFUN char * XMLCALL xmlMemoryStrdup (const char *str); XMLPUBFUN void * XMLCALL xmlMallocLoc (size_t size, const char *file, int line) LIBXML_ATTR_ALLOC_SIZE(1); XMLPUBFUN void * XMLCALL xmlReallocLoc (void *ptr, size_t size, const char *file, int line); XMLPUBFUN void * XMLCALL xmlMallocAtomicLoc (size_t size, const char *file, int line) LIBXML_ATTR_ALLOC_SIZE(1); XMLPUBFUN char * XMLCALL xmlMemStrdupLoc (const char *str, const char *file, int line); #ifdef DEBUG_MEMORY_LOCATION /** * xmlMalloc: * @size: number of bytes to allocate * * Wrapper for the malloc() function used in the XML library. * * Returns the pointer to the allocated area or NULL in case of error. */ #define xmlMalloc(size) xmlMallocLoc((size), __FILE__, __LINE__) /** * xmlMallocAtomic: * @size: number of bytes to allocate * * Wrapper for the malloc() function used in the XML library for allocation * of block not containing pointers to other areas. * * Returns the pointer to the allocated area or NULL in case of error. */ #define xmlMallocAtomic(size) xmlMallocAtomicLoc((size), __FILE__, __LINE__) /** * xmlRealloc: * @ptr: pointer to the existing allocated area * @size: number of bytes to allocate * * Wrapper for the realloc() function used in the XML library. * * Returns the pointer to the allocated area or NULL in case of error. */ #define xmlRealloc(ptr, size) xmlReallocLoc((ptr), (size), __FILE__, __LINE__) /** * xmlMemStrdup: * @str: pointer to the existing string * * Wrapper for the strdup() function, xmlStrdup() is usually preferred. * * Returns the pointer to the allocated area or NULL in case of error. */ #define xmlMemStrdup(str) xmlMemStrdupLoc((str), __FILE__, __LINE__) #endif /* DEBUG_MEMORY_LOCATION */ #ifdef __cplusplus } #endif /* __cplusplus */ #ifndef __XML_GLOBALS_H #ifndef __XML_THREADS_H__ #include #include #endif #endif #endif /* __DEBUG_MEMORY_ALLOC__ */ PK!S libxml/SAX.hnu[/* * Summary: Old SAX version 1 handler, deprecated * Description: DEPRECATED set of SAX version 1 interfaces used to * build the DOM tree. * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_SAX_H__ #define __XML_SAX_H__ #include #include #include #include #include #ifdef LIBXML_LEGACY_ENABLED #ifdef __cplusplus extern "C" { #endif XMLPUBFUN const xmlChar * XMLCALL getPublicId (void *ctx); XMLPUBFUN const xmlChar * XMLCALL getSystemId (void *ctx); XMLPUBFUN void XMLCALL setDocumentLocator (void *ctx, xmlSAXLocatorPtr loc); XMLPUBFUN int XMLCALL getLineNumber (void *ctx); XMLPUBFUN int XMLCALL getColumnNumber (void *ctx); XMLPUBFUN int XMLCALL isStandalone (void *ctx); XMLPUBFUN int XMLCALL hasInternalSubset (void *ctx); XMLPUBFUN int XMLCALL hasExternalSubset (void *ctx); XMLPUBFUN void XMLCALL internalSubset (void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN void XMLCALL externalSubset (void *ctx, const xmlChar *name, const xmlChar *ExternalID, const xmlChar *SystemID); XMLPUBFUN xmlEntityPtr XMLCALL getEntity (void *ctx, const xmlChar *name); XMLPUBFUN xmlEntityPtr XMLCALL getParameterEntity (void *ctx, const xmlChar *name); XMLPUBFUN xmlParserInputPtr XMLCALL resolveEntity (void *ctx, const xmlChar *publicId, const xmlChar *systemId); XMLPUBFUN void XMLCALL entityDecl (void *ctx, const xmlChar *name, int type, const xmlChar *publicId, const xmlChar *systemId, xmlChar *content); XMLPUBFUN void XMLCALL attributeDecl (void *ctx, const xmlChar *elem, const xmlChar *fullname, int type, int def, const xmlChar *defaultValue, xmlEnumerationPtr tree); XMLPUBFUN void XMLCALL elementDecl (void *ctx, const xmlChar *name, int type, xmlElementContentPtr content); XMLPUBFUN void XMLCALL notationDecl (void *ctx, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId); XMLPUBFUN void XMLCALL unparsedEntityDecl (void *ctx, const xmlChar *name, const xmlChar *publicId, const xmlChar *systemId, const xmlChar *notationName); XMLPUBFUN void XMLCALL startDocument (void *ctx); XMLPUBFUN void XMLCALL endDocument (void *ctx); XMLPUBFUN void XMLCALL attribute (void *ctx, const xmlChar *fullname, const xmlChar *value); XMLPUBFUN void XMLCALL startElement (void *ctx, const xmlChar *fullname, const xmlChar **atts); XMLPUBFUN void XMLCALL endElement (void *ctx, const xmlChar *name); XMLPUBFUN void XMLCALL reference (void *ctx, const xmlChar *name); XMLPUBFUN void XMLCALL characters (void *ctx, const xmlChar *ch, int len); XMLPUBFUN void XMLCALL ignorableWhitespace (void *ctx, const xmlChar *ch, int len); XMLPUBFUN void XMLCALL processingInstruction (void *ctx, const xmlChar *target, const xmlChar *data); XMLPUBFUN void XMLCALL globalNamespace (void *ctx, const xmlChar *href, const xmlChar *prefix); XMLPUBFUN void XMLCALL setNamespace (void *ctx, const xmlChar *name); XMLPUBFUN xmlNsPtr XMLCALL getNamespace (void *ctx); XMLPUBFUN int XMLCALL checkNamespace (void *ctx, xmlChar *nameSpace); XMLPUBFUN void XMLCALL namespaceDecl (void *ctx, const xmlChar *href, const xmlChar *prefix); XMLPUBFUN void XMLCALL comment (void *ctx, const xmlChar *value); XMLPUBFUN void XMLCALL cdataBlock (void *ctx, const xmlChar *value, int len); #ifdef LIBXML_SAX1_ENABLED XMLPUBFUN void XMLCALL initxmlDefaultSAXHandler (xmlSAXHandlerV1 *hdlr, int warning); #ifdef LIBXML_HTML_ENABLED XMLPUBFUN void XMLCALL inithtmlDefaultSAXHandler (xmlSAXHandlerV1 *hdlr); #endif #ifdef LIBXML_DOCB_ENABLED XMLPUBFUN void XMLCALL initdocbDefaultSAXHandler (xmlSAXHandlerV1 *hdlr); #endif #endif /* LIBXML_SAX1_ENABLED */ #ifdef __cplusplus } #endif #endif /* LIBXML_LEGACY_ENABLED */ #endif /* __XML_SAX_H__ */ PK!< pfpflibxml/schemasInternals.hnu[/* * Summary: internal interfaces for XML Schemas * Description: internal interfaces for the XML Schemas handling * and schema validity checking * The Schemas development is a Work In Progress. * Some of those interfaces are not guaranteed to be API or ABI stable ! * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_SCHEMA_INTERNALS_H__ #define __XML_SCHEMA_INTERNALS_H__ #include #ifdef LIBXML_SCHEMAS_ENABLED #include #include #include #ifdef __cplusplus extern "C" { #endif typedef enum { XML_SCHEMAS_UNKNOWN = 0, XML_SCHEMAS_STRING = 1, XML_SCHEMAS_NORMSTRING = 2, XML_SCHEMAS_DECIMAL = 3, XML_SCHEMAS_TIME = 4, XML_SCHEMAS_GDAY = 5, XML_SCHEMAS_GMONTH = 6, XML_SCHEMAS_GMONTHDAY = 7, XML_SCHEMAS_GYEAR = 8, XML_SCHEMAS_GYEARMONTH = 9, XML_SCHEMAS_DATE = 10, XML_SCHEMAS_DATETIME = 11, XML_SCHEMAS_DURATION = 12, XML_SCHEMAS_FLOAT = 13, XML_SCHEMAS_DOUBLE = 14, XML_SCHEMAS_BOOLEAN = 15, XML_SCHEMAS_TOKEN = 16, XML_SCHEMAS_LANGUAGE = 17, XML_SCHEMAS_NMTOKEN = 18, XML_SCHEMAS_NMTOKENS = 19, XML_SCHEMAS_NAME = 20, XML_SCHEMAS_QNAME = 21, XML_SCHEMAS_NCNAME = 22, XML_SCHEMAS_ID = 23, XML_SCHEMAS_IDREF = 24, XML_SCHEMAS_IDREFS = 25, XML_SCHEMAS_ENTITY = 26, XML_SCHEMAS_ENTITIES = 27, XML_SCHEMAS_NOTATION = 28, XML_SCHEMAS_ANYURI = 29, XML_SCHEMAS_INTEGER = 30, XML_SCHEMAS_NPINTEGER = 31, XML_SCHEMAS_NINTEGER = 32, XML_SCHEMAS_NNINTEGER = 33, XML_SCHEMAS_PINTEGER = 34, XML_SCHEMAS_INT = 35, XML_SCHEMAS_UINT = 36, XML_SCHEMAS_LONG = 37, XML_SCHEMAS_ULONG = 38, XML_SCHEMAS_SHORT = 39, XML_SCHEMAS_USHORT = 40, XML_SCHEMAS_BYTE = 41, XML_SCHEMAS_UBYTE = 42, XML_SCHEMAS_HEXBINARY = 43, XML_SCHEMAS_BASE64BINARY = 44, XML_SCHEMAS_ANYTYPE = 45, XML_SCHEMAS_ANYSIMPLETYPE = 46 } xmlSchemaValType; /* * XML Schemas defines multiple type of types. */ typedef enum { XML_SCHEMA_TYPE_BASIC = 1, /* A built-in datatype */ XML_SCHEMA_TYPE_ANY, XML_SCHEMA_TYPE_FACET, XML_SCHEMA_TYPE_SIMPLE, XML_SCHEMA_TYPE_COMPLEX, XML_SCHEMA_TYPE_SEQUENCE = 6, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL, XML_SCHEMA_TYPE_SIMPLE_CONTENT, XML_SCHEMA_TYPE_COMPLEX_CONTENT, XML_SCHEMA_TYPE_UR, XML_SCHEMA_TYPE_RESTRICTION, XML_SCHEMA_TYPE_EXTENSION, XML_SCHEMA_TYPE_ELEMENT, XML_SCHEMA_TYPE_ATTRIBUTE, XML_SCHEMA_TYPE_ATTRIBUTEGROUP, XML_SCHEMA_TYPE_GROUP, XML_SCHEMA_TYPE_NOTATION, XML_SCHEMA_TYPE_LIST, XML_SCHEMA_TYPE_UNION, XML_SCHEMA_TYPE_ANY_ATTRIBUTE, XML_SCHEMA_TYPE_IDC_UNIQUE, XML_SCHEMA_TYPE_IDC_KEY, XML_SCHEMA_TYPE_IDC_KEYREF, XML_SCHEMA_TYPE_PARTICLE = 25, XML_SCHEMA_TYPE_ATTRIBUTE_USE, XML_SCHEMA_FACET_MININCLUSIVE = 1000, XML_SCHEMA_FACET_MINEXCLUSIVE, XML_SCHEMA_FACET_MAXINCLUSIVE, XML_SCHEMA_FACET_MAXEXCLUSIVE, XML_SCHEMA_FACET_TOTALDIGITS, XML_SCHEMA_FACET_FRACTIONDIGITS, XML_SCHEMA_FACET_PATTERN, XML_SCHEMA_FACET_ENUMERATION, XML_SCHEMA_FACET_WHITESPACE, XML_SCHEMA_FACET_LENGTH, XML_SCHEMA_FACET_MAXLENGTH, XML_SCHEMA_FACET_MINLENGTH, XML_SCHEMA_EXTRA_QNAMEREF = 2000, XML_SCHEMA_EXTRA_ATTR_USE_PROHIB } xmlSchemaTypeType; typedef enum { XML_SCHEMA_CONTENT_UNKNOWN = 0, XML_SCHEMA_CONTENT_EMPTY = 1, XML_SCHEMA_CONTENT_ELEMENTS, XML_SCHEMA_CONTENT_MIXED, XML_SCHEMA_CONTENT_SIMPLE, XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS, /* Obsolete */ XML_SCHEMA_CONTENT_BASIC, XML_SCHEMA_CONTENT_ANY } xmlSchemaContentType; typedef struct _xmlSchemaVal xmlSchemaVal; typedef xmlSchemaVal *xmlSchemaValPtr; typedef struct _xmlSchemaType xmlSchemaType; typedef xmlSchemaType *xmlSchemaTypePtr; typedef struct _xmlSchemaFacet xmlSchemaFacet; typedef xmlSchemaFacet *xmlSchemaFacetPtr; /** * Annotation */ typedef struct _xmlSchemaAnnot xmlSchemaAnnot; typedef xmlSchemaAnnot *xmlSchemaAnnotPtr; struct _xmlSchemaAnnot { struct _xmlSchemaAnnot *next; xmlNodePtr content; /* the annotation */ }; /** * XML_SCHEMAS_ANYATTR_SKIP: * * Skip unknown attribute from validation * Obsolete, not used anymore. */ #define XML_SCHEMAS_ANYATTR_SKIP 1 /** * XML_SCHEMAS_ANYATTR_LAX: * * Ignore validation non definition on attributes * Obsolete, not used anymore. */ #define XML_SCHEMAS_ANYATTR_LAX 2 /** * XML_SCHEMAS_ANYATTR_STRICT: * * Apply strict validation rules on attributes * Obsolete, not used anymore. */ #define XML_SCHEMAS_ANYATTR_STRICT 3 /** * XML_SCHEMAS_ANY_SKIP: * * Skip unknown attribute from validation */ #define XML_SCHEMAS_ANY_SKIP 1 /** * XML_SCHEMAS_ANY_LAX: * * Used by wildcards. * Validate if type found, don't worry if not found */ #define XML_SCHEMAS_ANY_LAX 2 /** * XML_SCHEMAS_ANY_STRICT: * * Used by wildcards. * Apply strict validation rules */ #define XML_SCHEMAS_ANY_STRICT 3 /** * XML_SCHEMAS_ATTR_USE_PROHIBITED: * * Used by wildcards. * The attribute is prohibited. */ #define XML_SCHEMAS_ATTR_USE_PROHIBITED 0 /** * XML_SCHEMAS_ATTR_USE_REQUIRED: * * The attribute is required. */ #define XML_SCHEMAS_ATTR_USE_REQUIRED 1 /** * XML_SCHEMAS_ATTR_USE_OPTIONAL: * * The attribute is optional. */ #define XML_SCHEMAS_ATTR_USE_OPTIONAL 2 /** * XML_SCHEMAS_ATTR_GLOBAL: * * allow elements in no namespace */ #define XML_SCHEMAS_ATTR_GLOBAL 1 << 0 /** * XML_SCHEMAS_ATTR_NSDEFAULT: * * allow elements in no namespace */ #define XML_SCHEMAS_ATTR_NSDEFAULT 1 << 7 /** * XML_SCHEMAS_ATTR_INTERNAL_RESOLVED: * * this is set when the "type" and "ref" references * have been resolved. */ #define XML_SCHEMAS_ATTR_INTERNAL_RESOLVED 1 << 8 /** * XML_SCHEMAS_ATTR_FIXED: * * the attribute has a fixed value */ #define XML_SCHEMAS_ATTR_FIXED 1 << 9 /** * xmlSchemaAttribute: * An attribute definition. */ typedef struct _xmlSchemaAttribute xmlSchemaAttribute; typedef xmlSchemaAttribute *xmlSchemaAttributePtr; struct _xmlSchemaAttribute { xmlSchemaTypeType type; struct _xmlSchemaAttribute *next; /* the next attribute (not used?) */ const xmlChar *name; /* the name of the declaration */ const xmlChar *id; /* Deprecated; not used */ const xmlChar *ref; /* Deprecated; not used */ const xmlChar *refNs; /* Deprecated; not used */ const xmlChar *typeName; /* the local name of the type definition */ const xmlChar *typeNs; /* the ns URI of the type definition */ xmlSchemaAnnotPtr annot; xmlSchemaTypePtr base; /* Deprecated; not used */ int occurs; /* Deprecated; not used */ const xmlChar *defValue; /* The initial value of the value constraint */ xmlSchemaTypePtr subtypes; /* the type definition */ xmlNodePtr node; const xmlChar *targetNamespace; int flags; const xmlChar *refPrefix; /* Deprecated; not used */ xmlSchemaValPtr defVal; /* The compiled value constraint */ xmlSchemaAttributePtr refDecl; /* Deprecated; not used */ }; /** * xmlSchemaAttributeLink: * Used to build a list of attribute uses on complexType definitions. * WARNING: Deprecated; not used. */ typedef struct _xmlSchemaAttributeLink xmlSchemaAttributeLink; typedef xmlSchemaAttributeLink *xmlSchemaAttributeLinkPtr; struct _xmlSchemaAttributeLink { struct _xmlSchemaAttributeLink *next;/* the next attribute link ... */ struct _xmlSchemaAttribute *attr;/* the linked attribute */ }; /** * XML_SCHEMAS_WILDCARD_COMPLETE: * * If the wildcard is complete. */ #define XML_SCHEMAS_WILDCARD_COMPLETE 1 << 0 /** * xmlSchemaCharValueLink: * Used to build a list of namespaces on wildcards. */ typedef struct _xmlSchemaWildcardNs xmlSchemaWildcardNs; typedef xmlSchemaWildcardNs *xmlSchemaWildcardNsPtr; struct _xmlSchemaWildcardNs { struct _xmlSchemaWildcardNs *next;/* the next constraint link ... */ const xmlChar *value;/* the value */ }; /** * xmlSchemaWildcard. * A wildcard. */ typedef struct _xmlSchemaWildcard xmlSchemaWildcard; typedef xmlSchemaWildcard *xmlSchemaWildcardPtr; struct _xmlSchemaWildcard { xmlSchemaTypeType type; /* The kind of type */ const xmlChar *id; /* Deprecated; not used */ xmlSchemaAnnotPtr annot; xmlNodePtr node; int minOccurs; /* Deprecated; not used */ int maxOccurs; /* Deprecated; not used */ int processContents; int any; /* Indicates if the ns constraint is of ##any */ xmlSchemaWildcardNsPtr nsSet; /* The list of allowed namespaces */ xmlSchemaWildcardNsPtr negNsSet; /* The negated namespace */ int flags; }; /** * XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED: * * The attribute wildcard has been built. */ #define XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED 1 << 0 /** * XML_SCHEMAS_ATTRGROUP_GLOBAL: * * The attribute group has been defined. */ #define XML_SCHEMAS_ATTRGROUP_GLOBAL 1 << 1 /** * XML_SCHEMAS_ATTRGROUP_MARKED: * * Marks the attr group as marked; used for circular checks. */ #define XML_SCHEMAS_ATTRGROUP_MARKED 1 << 2 /** * XML_SCHEMAS_ATTRGROUP_REDEFINED: * * The attr group was redefined. */ #define XML_SCHEMAS_ATTRGROUP_REDEFINED 1 << 3 /** * XML_SCHEMAS_ATTRGROUP_HAS_REFS: * * Whether this attr. group contains attr. group references. */ #define XML_SCHEMAS_ATTRGROUP_HAS_REFS 1 << 4 /** * An attribute group definition. * * xmlSchemaAttribute and xmlSchemaAttributeGroup start of structures * must be kept similar */ typedef struct _xmlSchemaAttributeGroup xmlSchemaAttributeGroup; typedef xmlSchemaAttributeGroup *xmlSchemaAttributeGroupPtr; struct _xmlSchemaAttributeGroup { xmlSchemaTypeType type; /* The kind of type */ struct _xmlSchemaAttribute *next;/* the next attribute if in a group ... */ const xmlChar *name; const xmlChar *id; const xmlChar *ref; /* Deprecated; not used */ const xmlChar *refNs; /* Deprecated; not used */ xmlSchemaAnnotPtr annot; xmlSchemaAttributePtr attributes; /* Deprecated; not used */ xmlNodePtr node; int flags; xmlSchemaWildcardPtr attributeWildcard; const xmlChar *refPrefix; /* Deprecated; not used */ xmlSchemaAttributeGroupPtr refItem; /* Deprecated; not used */ const xmlChar *targetNamespace; void *attrUses; }; /** * xmlSchemaTypeLink: * Used to build a list of types (e.g. member types of * simpleType with variety "union"). */ typedef struct _xmlSchemaTypeLink xmlSchemaTypeLink; typedef xmlSchemaTypeLink *xmlSchemaTypeLinkPtr; struct _xmlSchemaTypeLink { struct _xmlSchemaTypeLink *next;/* the next type link ... */ xmlSchemaTypePtr type;/* the linked type */ }; /** * xmlSchemaFacetLink: * Used to build a list of facets. */ typedef struct _xmlSchemaFacetLink xmlSchemaFacetLink; typedef xmlSchemaFacetLink *xmlSchemaFacetLinkPtr; struct _xmlSchemaFacetLink { struct _xmlSchemaFacetLink *next;/* the next facet link ... */ xmlSchemaFacetPtr facet;/* the linked facet */ }; /** * XML_SCHEMAS_TYPE_MIXED: * * the element content type is mixed */ #define XML_SCHEMAS_TYPE_MIXED 1 << 0 /** * XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION: * * the simple or complex type has a derivation method of "extension". */ #define XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION 1 << 1 /** * XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION: * * the simple or complex type has a derivation method of "restriction". */ #define XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION 1 << 2 /** * XML_SCHEMAS_TYPE_GLOBAL: * * the type is global */ #define XML_SCHEMAS_TYPE_GLOBAL 1 << 3 /** * XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD: * * the complexType owns an attribute wildcard, i.e. * it can be freed by the complexType */ #define XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD 1 << 4 /* Obsolete. */ /** * XML_SCHEMAS_TYPE_VARIETY_ABSENT: * * the simpleType has a variety of "absent". * TODO: Actually not necessary :-/, since if * none of the variety flags occur then it's * automatically absent. */ #define XML_SCHEMAS_TYPE_VARIETY_ABSENT 1 << 5 /** * XML_SCHEMAS_TYPE_VARIETY_LIST: * * the simpleType has a variety of "list". */ #define XML_SCHEMAS_TYPE_VARIETY_LIST 1 << 6 /** * XML_SCHEMAS_TYPE_VARIETY_UNION: * * the simpleType has a variety of "union". */ #define XML_SCHEMAS_TYPE_VARIETY_UNION 1 << 7 /** * XML_SCHEMAS_TYPE_VARIETY_ATOMIC: * * the simpleType has a variety of "union". */ #define XML_SCHEMAS_TYPE_VARIETY_ATOMIC 1 << 8 /** * XML_SCHEMAS_TYPE_FINAL_EXTENSION: * * the complexType has a final of "extension". */ #define XML_SCHEMAS_TYPE_FINAL_EXTENSION 1 << 9 /** * XML_SCHEMAS_TYPE_FINAL_RESTRICTION: * * the simpleType/complexType has a final of "restriction". */ #define XML_SCHEMAS_TYPE_FINAL_RESTRICTION 1 << 10 /** * XML_SCHEMAS_TYPE_FINAL_LIST: * * the simpleType has a final of "list". */ #define XML_SCHEMAS_TYPE_FINAL_LIST 1 << 11 /** * XML_SCHEMAS_TYPE_FINAL_UNION: * * the simpleType has a final of "union". */ #define XML_SCHEMAS_TYPE_FINAL_UNION 1 << 12 /** * XML_SCHEMAS_TYPE_FINAL_DEFAULT: * * the simpleType has a final of "default". */ #define XML_SCHEMAS_TYPE_FINAL_DEFAULT 1 << 13 /** * XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE: * * Marks the item as a builtin primitive. */ #define XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE 1 << 14 /** * XML_SCHEMAS_TYPE_MARKED: * * Marks the item as marked; used for circular checks. */ #define XML_SCHEMAS_TYPE_MARKED 1 << 16 /** * XML_SCHEMAS_TYPE_BLOCK_DEFAULT: * * the complexType did not specify 'block' so use the default of the * item. */ #define XML_SCHEMAS_TYPE_BLOCK_DEFAULT 1 << 17 /** * XML_SCHEMAS_TYPE_BLOCK_EXTENSION: * * the complexType has a 'block' of "extension". */ #define XML_SCHEMAS_TYPE_BLOCK_EXTENSION 1 << 18 /** * XML_SCHEMAS_TYPE_BLOCK_RESTRICTION: * * the complexType has a 'block' of "restriction". */ #define XML_SCHEMAS_TYPE_BLOCK_RESTRICTION 1 << 19 /** * XML_SCHEMAS_TYPE_ABSTRACT: * * the simple/complexType is abstract. */ #define XML_SCHEMAS_TYPE_ABSTRACT 1 << 20 /** * XML_SCHEMAS_TYPE_FACETSNEEDVALUE: * * indicates if the facets need a computed value */ #define XML_SCHEMAS_TYPE_FACETSNEEDVALUE 1 << 21 /** * XML_SCHEMAS_TYPE_INTERNAL_RESOLVED: * * indicates that the type was typefixed */ #define XML_SCHEMAS_TYPE_INTERNAL_RESOLVED 1 << 22 /** * XML_SCHEMAS_TYPE_INTERNAL_INVALID: * * indicates that the type is invalid */ #define XML_SCHEMAS_TYPE_INTERNAL_INVALID 1 << 23 /** * XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE: * * a whitespace-facet value of "preserve" */ #define XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE 1 << 24 /** * XML_SCHEMAS_TYPE_WHITESPACE_REPLACE: * * a whitespace-facet value of "replace" */ #define XML_SCHEMAS_TYPE_WHITESPACE_REPLACE 1 << 25 /** * XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE: * * a whitespace-facet value of "collapse" */ #define XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE 1 << 26 /** * XML_SCHEMAS_TYPE_HAS_FACETS: * * has facets */ #define XML_SCHEMAS_TYPE_HAS_FACETS 1 << 27 /** * XML_SCHEMAS_TYPE_NORMVALUENEEDED: * * indicates if the facets (pattern) need a normalized value */ #define XML_SCHEMAS_TYPE_NORMVALUENEEDED 1 << 28 /** * XML_SCHEMAS_TYPE_FIXUP_1: * * First stage of fixup was done. */ #define XML_SCHEMAS_TYPE_FIXUP_1 1 << 29 /** * XML_SCHEMAS_TYPE_REDEFINED: * * The type was redefined. */ #define XML_SCHEMAS_TYPE_REDEFINED 1 << 30 /** * XML_SCHEMAS_TYPE_REDEFINING: * * The type redefines an other type. */ /* #define XML_SCHEMAS_TYPE_REDEFINING 1 << 31 */ /** * _xmlSchemaType: * * Schemas type definition. */ struct _xmlSchemaType { xmlSchemaTypeType type; /* The kind of type */ struct _xmlSchemaType *next; /* the next type if in a sequence ... */ const xmlChar *name; const xmlChar *id ; /* Deprecated; not used */ const xmlChar *ref; /* Deprecated; not used */ const xmlChar *refNs; /* Deprecated; not used */ xmlSchemaAnnotPtr annot; xmlSchemaTypePtr subtypes; xmlSchemaAttributePtr attributes; /* Deprecated; not used */ xmlNodePtr node; int minOccurs; /* Deprecated; not used */ int maxOccurs; /* Deprecated; not used */ int flags; xmlSchemaContentType contentType; const xmlChar *base; /* Base type's local name */ const xmlChar *baseNs; /* Base type's target namespace */ xmlSchemaTypePtr baseType; /* The base type component */ xmlSchemaFacetPtr facets; /* Local facets */ struct _xmlSchemaType *redef; /* Deprecated; not used */ int recurse; /* Obsolete */ xmlSchemaAttributeLinkPtr *attributeUses; /* Deprecated; not used */ xmlSchemaWildcardPtr attributeWildcard; int builtInType; /* Type of built-in types. */ xmlSchemaTypeLinkPtr memberTypes; /* member-types if a union type. */ xmlSchemaFacetLinkPtr facetSet; /* All facets (incl. inherited) */ const xmlChar *refPrefix; /* Deprecated; not used */ xmlSchemaTypePtr contentTypeDef; /* Used for the simple content of complex types. Could we use @subtypes for this? */ xmlRegexpPtr contModel; /* Holds the automaton of the content model */ const xmlChar *targetNamespace; void *attrUses; }; /* * xmlSchemaElement: * An element definition. * * xmlSchemaType, xmlSchemaFacet and xmlSchemaElement start of * structures must be kept similar */ /** * XML_SCHEMAS_ELEM_NILLABLE: * * the element is nillable */ #define XML_SCHEMAS_ELEM_NILLABLE 1 << 0 /** * XML_SCHEMAS_ELEM_GLOBAL: * * the element is global */ #define XML_SCHEMAS_ELEM_GLOBAL 1 << 1 /** * XML_SCHEMAS_ELEM_DEFAULT: * * the element has a default value */ #define XML_SCHEMAS_ELEM_DEFAULT 1 << 2 /** * XML_SCHEMAS_ELEM_FIXED: * * the element has a fixed value */ #define XML_SCHEMAS_ELEM_FIXED 1 << 3 /** * XML_SCHEMAS_ELEM_ABSTRACT: * * the element is abstract */ #define XML_SCHEMAS_ELEM_ABSTRACT 1 << 4 /** * XML_SCHEMAS_ELEM_TOPLEVEL: * * the element is top level * obsolete: use XML_SCHEMAS_ELEM_GLOBAL instead */ #define XML_SCHEMAS_ELEM_TOPLEVEL 1 << 5 /** * XML_SCHEMAS_ELEM_REF: * * the element is a reference to a type */ #define XML_SCHEMAS_ELEM_REF 1 << 6 /** * XML_SCHEMAS_ELEM_NSDEFAULT: * * allow elements in no namespace * Obsolete, not used anymore. */ #define XML_SCHEMAS_ELEM_NSDEFAULT 1 << 7 /** * XML_SCHEMAS_ELEM_INTERNAL_RESOLVED: * * this is set when "type", "ref", "substitutionGroup" * references have been resolved. */ #define XML_SCHEMAS_ELEM_INTERNAL_RESOLVED 1 << 8 /** * XML_SCHEMAS_ELEM_CIRCULAR: * * a helper flag for the search of circular references. */ #define XML_SCHEMAS_ELEM_CIRCULAR 1 << 9 /** * XML_SCHEMAS_ELEM_BLOCK_ABSENT: * * the "block" attribute is absent */ #define XML_SCHEMAS_ELEM_BLOCK_ABSENT 1 << 10 /** * XML_SCHEMAS_ELEM_BLOCK_EXTENSION: * * disallowed substitutions are absent */ #define XML_SCHEMAS_ELEM_BLOCK_EXTENSION 1 << 11 /** * XML_SCHEMAS_ELEM_BLOCK_RESTRICTION: * * disallowed substitutions: "restriction" */ #define XML_SCHEMAS_ELEM_BLOCK_RESTRICTION 1 << 12 /** * XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION: * * disallowed substitutions: "substitution" */ #define XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION 1 << 13 /** * XML_SCHEMAS_ELEM_FINAL_ABSENT: * * substitution group exclusions are absent */ #define XML_SCHEMAS_ELEM_FINAL_ABSENT 1 << 14 /** * XML_SCHEMAS_ELEM_FINAL_EXTENSION: * * substitution group exclusions: "extension" */ #define XML_SCHEMAS_ELEM_FINAL_EXTENSION 1 << 15 /** * XML_SCHEMAS_ELEM_FINAL_RESTRICTION: * * substitution group exclusions: "restriction" */ #define XML_SCHEMAS_ELEM_FINAL_RESTRICTION 1 << 16 /** * XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD: * * the declaration is a substitution group head */ #define XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD 1 << 17 /** * XML_SCHEMAS_ELEM_INTERNAL_CHECKED: * * this is set when the elem decl has been checked against * all constraints */ #define XML_SCHEMAS_ELEM_INTERNAL_CHECKED 1 << 18 typedef struct _xmlSchemaElement xmlSchemaElement; typedef xmlSchemaElement *xmlSchemaElementPtr; struct _xmlSchemaElement { xmlSchemaTypeType type; /* The kind of type */ struct _xmlSchemaType *next; /* Not used? */ const xmlChar *name; const xmlChar *id; /* Deprecated; not used */ const xmlChar *ref; /* Deprecated; not used */ const xmlChar *refNs; /* Deprecated; not used */ xmlSchemaAnnotPtr annot; xmlSchemaTypePtr subtypes; /* the type definition */ xmlSchemaAttributePtr attributes; xmlNodePtr node; int minOccurs; /* Deprecated; not used */ int maxOccurs; /* Deprecated; not used */ int flags; const xmlChar *targetNamespace; const xmlChar *namedType; const xmlChar *namedTypeNs; const xmlChar *substGroup; const xmlChar *substGroupNs; const xmlChar *scope; const xmlChar *value; /* The original value of the value constraint. */ struct _xmlSchemaElement *refDecl; /* This will now be used for the substitution group affiliation */ xmlRegexpPtr contModel; /* Obsolete for WXS, maybe used for RelaxNG */ xmlSchemaContentType contentType; const xmlChar *refPrefix; /* Deprecated; not used */ xmlSchemaValPtr defVal; /* The compiled value constraint. */ void *idcs; /* The identity-constraint defs */ }; /* * XML_SCHEMAS_FACET_UNKNOWN: * * unknown facet handling */ #define XML_SCHEMAS_FACET_UNKNOWN 0 /* * XML_SCHEMAS_FACET_PRESERVE: * * preserve the type of the facet */ #define XML_SCHEMAS_FACET_PRESERVE 1 /* * XML_SCHEMAS_FACET_REPLACE: * * replace the type of the facet */ #define XML_SCHEMAS_FACET_REPLACE 2 /* * XML_SCHEMAS_FACET_COLLAPSE: * * collapse the types of the facet */ #define XML_SCHEMAS_FACET_COLLAPSE 3 /** * A facet definition. */ struct _xmlSchemaFacet { xmlSchemaTypeType type; /* The kind of type */ struct _xmlSchemaFacet *next;/* the next type if in a sequence ... */ const xmlChar *value; /* The original value */ const xmlChar *id; /* Obsolete */ xmlSchemaAnnotPtr annot; xmlNodePtr node; int fixed; /* XML_SCHEMAS_FACET_PRESERVE, etc. */ int whitespace; xmlSchemaValPtr val; /* The compiled value */ xmlRegexpPtr regexp; /* The regex for patterns */ }; /** * A notation definition. */ typedef struct _xmlSchemaNotation xmlSchemaNotation; typedef xmlSchemaNotation *xmlSchemaNotationPtr; struct _xmlSchemaNotation { xmlSchemaTypeType type; /* The kind of type */ const xmlChar *name; xmlSchemaAnnotPtr annot; const xmlChar *identifier; const xmlChar *targetNamespace; }; /* * TODO: Actually all those flags used for the schema should sit * on the schema parser context, since they are used only * during parsing an XML schema document, and not available * on the component level as per spec. */ /** * XML_SCHEMAS_QUALIF_ELEM: * * Reflects elementFormDefault == qualified in * an XML schema document. */ #define XML_SCHEMAS_QUALIF_ELEM 1 << 0 /** * XML_SCHEMAS_QUALIF_ATTR: * * Reflects attributeFormDefault == qualified in * an XML schema document. */ #define XML_SCHEMAS_QUALIF_ATTR 1 << 1 /** * XML_SCHEMAS_FINAL_DEFAULT_EXTENSION: * * the schema has "extension" in the set of finalDefault. */ #define XML_SCHEMAS_FINAL_DEFAULT_EXTENSION 1 << 2 /** * XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION: * * the schema has "restriction" in the set of finalDefault. */ #define XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION 1 << 3 /** * XML_SCHEMAS_FINAL_DEFAULT_LIST: * * the schema has "list" in the set of finalDefault. */ #define XML_SCHEMAS_FINAL_DEFAULT_LIST 1 << 4 /** * XML_SCHEMAS_FINAL_DEFAULT_UNION: * * the schema has "union" in the set of finalDefault. */ #define XML_SCHEMAS_FINAL_DEFAULT_UNION 1 << 5 /** * XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION: * * the schema has "extension" in the set of blockDefault. */ #define XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION 1 << 6 /** * XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION: * * the schema has "restriction" in the set of blockDefault. */ #define XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION 1 << 7 /** * XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION: * * the schema has "substitution" in the set of blockDefault. */ #define XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION 1 << 8 /** * XML_SCHEMAS_INCLUDING_CONVERT_NS: * * the schema is currently including an other schema with * no target namespace. */ #define XML_SCHEMAS_INCLUDING_CONVERT_NS 1 << 9 /** * _xmlSchema: * * A Schemas definition */ struct _xmlSchema { const xmlChar *name; /* schema name */ const xmlChar *targetNamespace; /* the target namespace */ const xmlChar *version; const xmlChar *id; /* Obsolete */ xmlDocPtr doc; xmlSchemaAnnotPtr annot; int flags; xmlHashTablePtr typeDecl; xmlHashTablePtr attrDecl; xmlHashTablePtr attrgrpDecl; xmlHashTablePtr elemDecl; xmlHashTablePtr notaDecl; xmlHashTablePtr schemasImports; void *_private; /* unused by the library for users or bindings */ xmlHashTablePtr groupDecl; xmlDictPtr dict; void *includes; /* the includes, this is opaque for now */ int preserve; /* whether to free the document */ int counter; /* used to give anonymous components unique names */ xmlHashTablePtr idcDef; /* All identity-constraint defs. */ void *volatiles; /* Obsolete */ }; XMLPUBFUN void XMLCALL xmlSchemaFreeType (xmlSchemaTypePtr type); XMLPUBFUN void XMLCALL xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard); #ifdef __cplusplus } #endif #endif /* LIBXML_SCHEMAS_ENABLED */ #endif /* __XML_SCHEMA_INTERNALS_H__ */ PK!zb  libxml/xpointer.hnu[/* * Summary: API to handle XML Pointers * Description: API to handle XML Pointers * Base implementation was made accordingly to * W3C Candidate Recommendation 7 June 2000 * http://www.w3.org/TR/2000/CR-xptr-20000607 * * Added support for the element() scheme described in: * W3C Proposed Recommendation 13 November 2002 * http://www.w3.org/TR/2002/PR-xptr-element-20021113/ * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XPTR_H__ #define __XML_XPTR_H__ #include #ifdef LIBXML_XPTR_ENABLED #include #include #ifdef __cplusplus extern "C" { #endif /* * A Location Set */ typedef struct _xmlLocationSet xmlLocationSet; typedef xmlLocationSet *xmlLocationSetPtr; struct _xmlLocationSet { int locNr; /* number of locations in the set */ int locMax; /* size of the array as allocated */ xmlXPathObjectPtr *locTab;/* array of locations */ }; /* * Handling of location sets. */ XMLPUBFUN xmlLocationSetPtr XMLCALL xmlXPtrLocationSetCreate (xmlXPathObjectPtr val); XMLPUBFUN void XMLCALL xmlXPtrFreeLocationSet (xmlLocationSetPtr obj); XMLPUBFUN xmlLocationSetPtr XMLCALL xmlXPtrLocationSetMerge (xmlLocationSetPtr val1, xmlLocationSetPtr val2); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewRange (xmlNodePtr start, int startindex, xmlNodePtr end, int endindex); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewRangePoints (xmlXPathObjectPtr start, xmlXPathObjectPtr end); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewRangeNodePoint (xmlNodePtr start, xmlXPathObjectPtr end); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewRangePointNode (xmlXPathObjectPtr start, xmlNodePtr end); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewRangeNodes (xmlNodePtr start, xmlNodePtr end); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewLocationSetNodes (xmlNodePtr start, xmlNodePtr end); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewLocationSetNodeSet(xmlNodeSetPtr set); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewRangeNodeObject (xmlNodePtr start, xmlXPathObjectPtr end); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrNewCollapsedRange (xmlNodePtr start); XMLPUBFUN void XMLCALL xmlXPtrLocationSetAdd (xmlLocationSetPtr cur, xmlXPathObjectPtr val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrWrapLocationSet (xmlLocationSetPtr val); XMLPUBFUN void XMLCALL xmlXPtrLocationSetDel (xmlLocationSetPtr cur, xmlXPathObjectPtr val); XMLPUBFUN void XMLCALL xmlXPtrLocationSetRemove (xmlLocationSetPtr cur, int val); /* * Functions. */ XMLPUBFUN xmlXPathContextPtr XMLCALL xmlXPtrNewContext (xmlDocPtr doc, xmlNodePtr here, xmlNodePtr origin); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPtrEval (const xmlChar *str, xmlXPathContextPtr ctx); XMLPUBFUN void XMLCALL xmlXPtrRangeToFunction (xmlXPathParserContextPtr ctxt, int nargs); XMLPUBFUN xmlNodePtr XMLCALL xmlXPtrBuildNodeList (xmlXPathObjectPtr obj); XMLPUBFUN void XMLCALL xmlXPtrEvalRangePredicate (xmlXPathParserContextPtr ctxt); #ifdef __cplusplus } #endif #endif /* LIBXML_XPTR_ENABLED */ #endif /* __XML_XPTR_H__ */ PK!Xrl+@@libxml/xpath.hnu[/* * Summary: XML Path Language implementation * Description: API for the XML Path Language implementation * * XML Path Language implementation * XPath is a language for addressing parts of an XML document, * designed to be used by both XSLT and XPointer * http://www.w3.org/TR/xpath * * Implements * W3C Recommendation 16 November 1999 * http://www.w3.org/TR/1999/REC-xpath-19991116 * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_XPATH_H__ #define __XML_XPATH_H__ #include #ifdef LIBXML_XPATH_ENABLED #include #include #include #endif /* LIBXML_XPATH_ENABLED */ #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) #ifdef __cplusplus extern "C" { #endif #endif /* LIBXML_XPATH_ENABLED or LIBXML_SCHEMAS_ENABLED */ #ifdef LIBXML_XPATH_ENABLED typedef struct _xmlXPathContext xmlXPathContext; typedef xmlXPathContext *xmlXPathContextPtr; typedef struct _xmlXPathParserContext xmlXPathParserContext; typedef xmlXPathParserContext *xmlXPathParserContextPtr; /** * The set of XPath error codes. */ typedef enum { XPATH_EXPRESSION_OK = 0, XPATH_NUMBER_ERROR, XPATH_UNFINISHED_LITERAL_ERROR, XPATH_START_LITERAL_ERROR, XPATH_VARIABLE_REF_ERROR, XPATH_UNDEF_VARIABLE_ERROR, XPATH_INVALID_PREDICATE_ERROR, XPATH_EXPR_ERROR, XPATH_UNCLOSED_ERROR, XPATH_UNKNOWN_FUNC_ERROR, XPATH_INVALID_OPERAND, XPATH_INVALID_TYPE, XPATH_INVALID_ARITY, XPATH_INVALID_CTXT_SIZE, XPATH_INVALID_CTXT_POSITION, XPATH_MEMORY_ERROR, XPTR_SYNTAX_ERROR, XPTR_RESOURCE_ERROR, XPTR_SUB_RESOURCE_ERROR, XPATH_UNDEF_PREFIX_ERROR, XPATH_ENCODING_ERROR, XPATH_INVALID_CHAR_ERROR, XPATH_INVALID_CTXT, XPATH_STACK_ERROR, XPATH_FORBID_VARIABLE_ERROR, XPATH_OP_LIMIT_EXCEEDED, XPATH_RECURSION_LIMIT_EXCEEDED } xmlXPathError; /* * A node-set (an unordered collection of nodes without duplicates). */ typedef struct _xmlNodeSet xmlNodeSet; typedef xmlNodeSet *xmlNodeSetPtr; struct _xmlNodeSet { int nodeNr; /* number of nodes in the set */ int nodeMax; /* size of the array as allocated */ xmlNodePtr *nodeTab; /* array of nodes in no particular order */ /* @@ with_ns to check whether namespace nodes should be looked at @@ */ }; /* * An expression is evaluated to yield an object, which * has one of the following four basic types: * - node-set * - boolean * - number * - string * * @@ XPointer will add more types ! */ typedef enum { XPATH_UNDEFINED = 0, XPATH_NODESET = 1, XPATH_BOOLEAN = 2, XPATH_NUMBER = 3, XPATH_STRING = 4, XPATH_POINT = 5, XPATH_RANGE = 6, XPATH_LOCATIONSET = 7, XPATH_USERS = 8, XPATH_XSLT_TREE = 9 /* An XSLT value tree, non modifiable */ } xmlXPathObjectType; typedef struct _xmlXPathObject xmlXPathObject; typedef xmlXPathObject *xmlXPathObjectPtr; struct _xmlXPathObject { xmlXPathObjectType type; xmlNodeSetPtr nodesetval; int boolval; double floatval; xmlChar *stringval; void *user; int index; void *user2; int index2; }; /** * xmlXPathConvertFunc: * @obj: an XPath object * @type: the number of the target type * * A conversion function is associated to a type and used to cast * the new type to primitive values. * * Returns -1 in case of error, 0 otherwise */ typedef int (*xmlXPathConvertFunc) (xmlXPathObjectPtr obj, int type); /* * Extra type: a name and a conversion function. */ typedef struct _xmlXPathType xmlXPathType; typedef xmlXPathType *xmlXPathTypePtr; struct _xmlXPathType { const xmlChar *name; /* the type name */ xmlXPathConvertFunc func; /* the conversion function */ }; /* * Extra variable: a name and a value. */ typedef struct _xmlXPathVariable xmlXPathVariable; typedef xmlXPathVariable *xmlXPathVariablePtr; struct _xmlXPathVariable { const xmlChar *name; /* the variable name */ xmlXPathObjectPtr value; /* the value */ }; /** * xmlXPathEvalFunc: * @ctxt: an XPath parser context * @nargs: the number of arguments passed to the function * * An XPath evaluation function, the parameters are on the XPath context stack. */ typedef void (*xmlXPathEvalFunc)(xmlXPathParserContextPtr ctxt, int nargs); /* * Extra function: a name and a evaluation function. */ typedef struct _xmlXPathFunct xmlXPathFunct; typedef xmlXPathFunct *xmlXPathFuncPtr; struct _xmlXPathFunct { const xmlChar *name; /* the function name */ xmlXPathEvalFunc func; /* the evaluation function */ }; /** * xmlXPathAxisFunc: * @ctxt: the XPath interpreter context * @cur: the previous node being explored on that axis * * An axis traversal function. To traverse an axis, the engine calls * the first time with cur == NULL and repeat until the function returns * NULL indicating the end of the axis traversal. * * Returns the next node in that axis or NULL if at the end of the axis. */ typedef xmlXPathObjectPtr (*xmlXPathAxisFunc) (xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr cur); /* * Extra axis: a name and an axis function. */ typedef struct _xmlXPathAxis xmlXPathAxis; typedef xmlXPathAxis *xmlXPathAxisPtr; struct _xmlXPathAxis { const xmlChar *name; /* the axis name */ xmlXPathAxisFunc func; /* the search function */ }; /** * xmlXPathFunction: * @ctxt: the XPath interprestation context * @nargs: the number of arguments * * An XPath function. * The arguments (if any) are popped out from the context stack * and the result is pushed on the stack. */ typedef void (*xmlXPathFunction) (xmlXPathParserContextPtr ctxt, int nargs); /* * Function and Variable Lookup. */ /** * xmlXPathVariableLookupFunc: * @ctxt: an XPath context * @name: name of the variable * @ns_uri: the namespace name hosting this variable * * Prototype for callbacks used to plug variable lookup in the XPath * engine. * * Returns the XPath object value or NULL if not found. */ typedef xmlXPathObjectPtr (*xmlXPathVariableLookupFunc) (void *ctxt, const xmlChar *name, const xmlChar *ns_uri); /** * xmlXPathFuncLookupFunc: * @ctxt: an XPath context * @name: name of the function * @ns_uri: the namespace name hosting this function * * Prototype for callbacks used to plug function lookup in the XPath * engine. * * Returns the XPath function or NULL if not found. */ typedef xmlXPathFunction (*xmlXPathFuncLookupFunc) (void *ctxt, const xmlChar *name, const xmlChar *ns_uri); /** * xmlXPathFlags: * Flags for XPath engine compilation and runtime */ /** * XML_XPATH_CHECKNS: * * check namespaces at compilation */ #define XML_XPATH_CHECKNS (1<<0) /** * XML_XPATH_NOVAR: * * forbid variables in expression */ #define XML_XPATH_NOVAR (1<<1) /** * xmlXPathContext: * * Expression evaluation occurs with respect to a context. * he context consists of: * - a node (the context node) * - a node list (the context node list) * - a set of variable bindings * - a function library * - the set of namespace declarations in scope for the expression * Following the switch to hash tables, this need to be trimmed up at * the next binary incompatible release. * The node may be modified when the context is passed to libxml2 * for an XPath evaluation so you may need to initialize it again * before the next call. */ struct _xmlXPathContext { xmlDocPtr doc; /* The current document */ xmlNodePtr node; /* The current node */ int nb_variables_unused; /* unused (hash table) */ int max_variables_unused; /* unused (hash table) */ xmlHashTablePtr varHash; /* Hash table of defined variables */ int nb_types; /* number of defined types */ int max_types; /* max number of types */ xmlXPathTypePtr types; /* Array of defined types */ int nb_funcs_unused; /* unused (hash table) */ int max_funcs_unused; /* unused (hash table) */ xmlHashTablePtr funcHash; /* Hash table of defined funcs */ int nb_axis; /* number of defined axis */ int max_axis; /* max number of axis */ xmlXPathAxisPtr axis; /* Array of defined axis */ /* the namespace nodes of the context node */ xmlNsPtr *namespaces; /* Array of namespaces */ int nsNr; /* number of namespace in scope */ void *user; /* function to free */ /* extra variables */ int contextSize; /* the context size */ int proximityPosition; /* the proximity position */ /* extra stuff for XPointer */ int xptr; /* is this an XPointer context? */ xmlNodePtr here; /* for here() */ xmlNodePtr origin; /* for origin() */ /* the set of namespace declarations in scope for the expression */ xmlHashTablePtr nsHash; /* The namespaces hash table */ xmlXPathVariableLookupFunc varLookupFunc;/* variable lookup func */ void *varLookupData; /* variable lookup data */ /* Possibility to link in an extra item */ void *extra; /* needed for XSLT */ /* The function name and URI when calling a function */ const xmlChar *function; const xmlChar *functionURI; /* function lookup function and data */ xmlXPathFuncLookupFunc funcLookupFunc;/* function lookup func */ void *funcLookupData; /* function lookup data */ /* temporary namespace lists kept for walking the namespace axis */ xmlNsPtr *tmpNsList; /* Array of namespaces */ int tmpNsNr; /* number of namespaces in scope */ /* error reporting mechanism */ void *userData; /* user specific data block */ xmlStructuredErrorFunc error; /* the callback in case of errors */ xmlError lastError; /* the last error */ xmlNodePtr debugNode; /* the source node XSLT */ /* dictionary */ xmlDictPtr dict; /* dictionary if any */ int flags; /* flags to control compilation */ /* Cache for reusal of XPath objects */ void *cache; /* Resource limits */ unsigned long opLimit; unsigned long opCount; int depth; }; /* * The structure of a compiled expression form is not public. */ typedef struct _xmlXPathCompExpr xmlXPathCompExpr; typedef xmlXPathCompExpr *xmlXPathCompExprPtr; /** * xmlXPathParserContext: * * An XPath parser context. It contains pure parsing information, * an xmlXPathContext, and the stack of objects. */ struct _xmlXPathParserContext { const xmlChar *cur; /* the current char being parsed */ const xmlChar *base; /* the full expression */ int error; /* error code */ xmlXPathContextPtr context; /* the evaluation context */ xmlXPathObjectPtr value; /* the current value */ int valueNr; /* number of values stacked */ int valueMax; /* max number of values stacked */ xmlXPathObjectPtr *valueTab; /* stack of values */ xmlXPathCompExprPtr comp; /* the precompiled expression */ int xptr; /* it this an XPointer expression */ xmlNodePtr ancestor; /* used for walking preceding axis */ int valueFrame; /* used to limit Pop on the stack */ }; /************************************************************************ * * * Public API * * * ************************************************************************/ /** * Objects and Nodesets handling */ XMLPUBVAR double xmlXPathNAN; XMLPUBVAR double xmlXPathPINF; XMLPUBVAR double xmlXPathNINF; /* These macros may later turn into functions */ /** * xmlXPathNodeSetGetLength: * @ns: a node-set * * Implement a functionality similar to the DOM NodeList.length. * * Returns the number of nodes in the node-set. */ #define xmlXPathNodeSetGetLength(ns) ((ns) ? (ns)->nodeNr : 0) /** * xmlXPathNodeSetItem: * @ns: a node-set * @index: index of a node in the set * * Implements a functionality similar to the DOM NodeList.item(). * * Returns the xmlNodePtr at the given @index in @ns or NULL if * @index is out of range (0 to length-1) */ #define xmlXPathNodeSetItem(ns, index) \ ((((ns) != NULL) && \ ((index) >= 0) && ((index) < (ns)->nodeNr)) ? \ (ns)->nodeTab[(index)] \ : NULL) /** * xmlXPathNodeSetIsEmpty: * @ns: a node-set * * Checks whether @ns is empty or not. * * Returns %TRUE if @ns is an empty node-set. */ #define xmlXPathNodeSetIsEmpty(ns) \ (((ns) == NULL) || ((ns)->nodeNr == 0) || ((ns)->nodeTab == NULL)) XMLPUBFUN void XMLCALL xmlXPathFreeObject (xmlXPathObjectPtr obj); XMLPUBFUN xmlNodeSetPtr XMLCALL xmlXPathNodeSetCreate (xmlNodePtr val); XMLPUBFUN void XMLCALL xmlXPathFreeNodeSetList (xmlXPathObjectPtr obj); XMLPUBFUN void XMLCALL xmlXPathFreeNodeSet (xmlNodeSetPtr obj); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathObjectCopy (xmlXPathObjectPtr val); XMLPUBFUN int XMLCALL xmlXPathCmpNodes (xmlNodePtr node1, xmlNodePtr node2); /** * Conversion functions to basic types. */ XMLPUBFUN int XMLCALL xmlXPathCastNumberToBoolean (double val); XMLPUBFUN int XMLCALL xmlXPathCastStringToBoolean (const xmlChar * val); XMLPUBFUN int XMLCALL xmlXPathCastNodeSetToBoolean(xmlNodeSetPtr ns); XMLPUBFUN int XMLCALL xmlXPathCastToBoolean (xmlXPathObjectPtr val); XMLPUBFUN double XMLCALL xmlXPathCastBooleanToNumber (int val); XMLPUBFUN double XMLCALL xmlXPathCastStringToNumber (const xmlChar * val); XMLPUBFUN double XMLCALL xmlXPathCastNodeToNumber (xmlNodePtr node); XMLPUBFUN double XMLCALL xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns); XMLPUBFUN double XMLCALL xmlXPathCastToNumber (xmlXPathObjectPtr val); XMLPUBFUN xmlChar * XMLCALL xmlXPathCastBooleanToString (int val); XMLPUBFUN xmlChar * XMLCALL xmlXPathCastNumberToString (double val); XMLPUBFUN xmlChar * XMLCALL xmlXPathCastNodeToString (xmlNodePtr node); XMLPUBFUN xmlChar * XMLCALL xmlXPathCastNodeSetToString (xmlNodeSetPtr ns); XMLPUBFUN xmlChar * XMLCALL xmlXPathCastToString (xmlXPathObjectPtr val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathConvertBoolean (xmlXPathObjectPtr val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathConvertNumber (xmlXPathObjectPtr val); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathConvertString (xmlXPathObjectPtr val); /** * Context handling. */ XMLPUBFUN xmlXPathContextPtr XMLCALL xmlXPathNewContext (xmlDocPtr doc); XMLPUBFUN void XMLCALL xmlXPathFreeContext (xmlXPathContextPtr ctxt); XMLPUBFUN int XMLCALL xmlXPathContextSetCache(xmlXPathContextPtr ctxt, int active, int value, int options); /** * Evaluation functions. */ XMLPUBFUN long XMLCALL xmlXPathOrderDocElems (xmlDocPtr doc); XMLPUBFUN int XMLCALL xmlXPathSetContextNode (xmlNodePtr node, xmlXPathContextPtr ctx); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathNodeEval (xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathEval (const xmlChar *str, xmlXPathContextPtr ctx); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathEvalExpression (const xmlChar *str, xmlXPathContextPtr ctxt); XMLPUBFUN int XMLCALL xmlXPathEvalPredicate (xmlXPathContextPtr ctxt, xmlXPathObjectPtr res); /** * Separate compilation/evaluation entry points. */ XMLPUBFUN xmlXPathCompExprPtr XMLCALL xmlXPathCompile (const xmlChar *str); XMLPUBFUN xmlXPathCompExprPtr XMLCALL xmlXPathCtxtCompile (xmlXPathContextPtr ctxt, const xmlChar *str); XMLPUBFUN xmlXPathObjectPtr XMLCALL xmlXPathCompiledEval (xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx); XMLPUBFUN int XMLCALL xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt); XMLPUBFUN void XMLCALL xmlXPathFreeCompExpr (xmlXPathCompExprPtr comp); #endif /* LIBXML_XPATH_ENABLED */ #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED) XMLPUBFUN void XMLCALL xmlXPathInit (void); XMLPUBFUN int XMLCALL xmlXPathIsNaN (double val); XMLPUBFUN int XMLCALL xmlXPathIsInf (double val); #ifdef __cplusplus } #endif #endif /* LIBXML_XPATH_ENABLED or LIBXML_SCHEMAS_ENABLED*/ #endif /* ! __XML_XPATH_H__ */ PK!hhlibxml/xmlversion.hnu[/* * Summary: compile-time version information * Description: compile-time version information for the XML library * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #ifndef __XML_VERSION_H__ #define __XML_VERSION_H__ #include #ifdef __cplusplus extern "C" { #endif /* * use those to be sure nothing nasty will happen if * your library and includes mismatch */ #ifndef LIBXML2_COMPILING_MSCCDEF XMLPUBFUN void XMLCALL xmlCheckVersion(int version); #endif /* LIBXML2_COMPILING_MSCCDEF */ /** * LIBXML_DOTTED_VERSION: * * the version string like "1.2.3" */ #define LIBXML_DOTTED_VERSION "2.9.14" /** * LIBXML_VERSION: * * the version number: 1.2.3 value is 10203 */ #define LIBXML_VERSION 20914 /** * LIBXML_VERSION_STRING: * * the version number string, 1.2.3 value is "10203" */ #define LIBXML_VERSION_STRING "20914" /** * LIBXML_VERSION_EXTRA: * * extra version information, used to show a git commit description */ #define LIBXML_VERSION_EXTRA "" /** * LIBXML_TEST_VERSION: * * Macro to check that the libxml version in use is compatible with * the version the software has been compiled against */ #define LIBXML_TEST_VERSION xmlCheckVersion(20914); #ifndef VMS #if 0 /** * WITH_TRIO: * * defined if the trio support need to be configured in */ #define WITH_TRIO #else /** * WITHOUT_TRIO: * * defined if the trio support should not be configured in */ #define WITHOUT_TRIO #endif #else /* VMS */ /** * WITH_TRIO: * * defined if the trio support need to be configured in */ #define WITH_TRIO 1 #endif /* VMS */ /** * LIBXML_THREAD_ENABLED: * * Whether the thread support is configured in */ #if 1 #define LIBXML_THREAD_ENABLED #endif /** * LIBXML_THREAD_ALLOC_ENABLED: * * Whether the allocation hooks are per-thread */ #if 0 #define LIBXML_THREAD_ALLOC_ENABLED #endif /** * LIBXML_TREE_ENABLED: * * Whether the DOM like tree manipulation API support is configured in */ #if 1 #define LIBXML_TREE_ENABLED #endif /** * LIBXML_OUTPUT_ENABLED: * * Whether the serialization/saving support is configured in */ #if 1 #define LIBXML_OUTPUT_ENABLED #endif /** * LIBXML_PUSH_ENABLED: * * Whether the push parsing interfaces are configured in */ #if 1 #define LIBXML_PUSH_ENABLED #endif /** * LIBXML_READER_ENABLED: * * Whether the xmlReader parsing interface is configured in */ #if 1 #define LIBXML_READER_ENABLED #endif /** * LIBXML_PATTERN_ENABLED: * * Whether the xmlPattern node selection interface is configured in */ #if 1 #define LIBXML_PATTERN_ENABLED #endif /** * LIBXML_WRITER_ENABLED: * * Whether the xmlWriter saving interface is configured in */ #if 1 #define LIBXML_WRITER_ENABLED #endif /** * LIBXML_SAX1_ENABLED: * * Whether the older SAX1 interface is configured in */ #if 1 #define LIBXML_SAX1_ENABLED #endif /** * LIBXML_FTP_ENABLED: * * Whether the FTP support is configured in */ #if 1 #define LIBXML_FTP_ENABLED #endif /** * LIBXML_HTTP_ENABLED: * * Whether the HTTP support is configured in */ #if 1 #define LIBXML_HTTP_ENABLED #endif /** * LIBXML_VALID_ENABLED: * * Whether the DTD validation support is configured in */ #if 1 #define LIBXML_VALID_ENABLED #endif /** * LIBXML_HTML_ENABLED: * * Whether the HTML support is configured in */ #if 1 #define LIBXML_HTML_ENABLED #endif /** * LIBXML_LEGACY_ENABLED: * * Whether the deprecated APIs are compiled in for compatibility */ #if 1 #define LIBXML_LEGACY_ENABLED #endif /** * LIBXML_C14N_ENABLED: * * Whether the Canonicalization support is configured in */ #if 1 #define LIBXML_C14N_ENABLED #endif /** * LIBXML_CATALOG_ENABLED: * * Whether the Catalog support is configured in */ #if 1 #define LIBXML_CATALOG_ENABLED #endif /** * LIBXML_DOCB_ENABLED: * * Whether the SGML Docbook support is configured in */ #if 1 #define LIBXML_DOCB_ENABLED #endif /** * LIBXML_XPATH_ENABLED: * * Whether XPath is configured in */ #if 1 #define LIBXML_XPATH_ENABLED #endif /** * LIBXML_XPTR_ENABLED: * * Whether XPointer is configured in */ #if 1 #define LIBXML_XPTR_ENABLED #endif /** * LIBXML_XINCLUDE_ENABLED: * * Whether XInclude is configured in */ #if 1 #define LIBXML_XINCLUDE_ENABLED #endif /** * LIBXML_ICONV_ENABLED: * * Whether iconv support is available */ #if 1 #define LIBXML_ICONV_ENABLED #endif /** * LIBXML_ICU_ENABLED: * * Whether icu support is available */ #if 0 #define LIBXML_ICU_ENABLED #endif /** * LIBXML_ISO8859X_ENABLED: * * Whether ISO-8859-* support is made available in case iconv is not */ #if 1 #define LIBXML_ISO8859X_ENABLED #endif /** * LIBXML_DEBUG_ENABLED: * * Whether Debugging module is configured in */ #if 1 #define LIBXML_DEBUG_ENABLED #endif /** * DEBUG_MEMORY_LOCATION: * * Whether the memory debugging is configured in */ #if 0 #define DEBUG_MEMORY_LOCATION #endif /** * LIBXML_DEBUG_RUNTIME: * * Whether the runtime debugging is configured in */ #if 0 #define LIBXML_DEBUG_RUNTIME #endif /** * LIBXML_UNICODE_ENABLED: * * Whether the Unicode related interfaces are compiled in */ #if 1 #define LIBXML_UNICODE_ENABLED #endif /** * LIBXML_REGEXP_ENABLED: * * Whether the regular expressions interfaces are compiled in */ #if 1 #define LIBXML_REGEXP_ENABLED #endif /** * LIBXML_AUTOMATA_ENABLED: * * Whether the automata interfaces are compiled in */ #if 1 #define LIBXML_AUTOMATA_ENABLED #endif /** * LIBXML_EXPR_ENABLED: * * Whether the formal expressions interfaces are compiled in * * This code is unused and disabled unconditionally for now. */ #if 0 #define LIBXML_EXPR_ENABLED #endif /** * LIBXML_SCHEMAS_ENABLED: * * Whether the Schemas validation interfaces are compiled in */ #if 1 #define LIBXML_SCHEMAS_ENABLED #endif /** * LIBXML_SCHEMATRON_ENABLED: * * Whether the Schematron validation interfaces are compiled in */ #if 1 #define LIBXML_SCHEMATRON_ENABLED #endif /** * LIBXML_MODULES_ENABLED: * * Whether the module interfaces are compiled in */ #if 1 #define LIBXML_MODULES_ENABLED /** * LIBXML_MODULE_EXTENSION: * * the string suffix used by dynamic modules (usually shared libraries) */ #define LIBXML_MODULE_EXTENSION ".so" #endif /** * LIBXML_ZLIB_ENABLED: * * Whether the Zlib support is compiled in */ #if 1 #define LIBXML_ZLIB_ENABLED #endif /** * LIBXML_LZMA_ENABLED: * * Whether the Lzma support is compiled in */ #if 0 #define LIBXML_LZMA_ENABLED #endif #ifdef __GNUC__ /** * ATTRIBUTE_UNUSED: * * Macro used to signal to GCC unused function parameters */ #ifndef ATTRIBUTE_UNUSED # if ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >= 7))) # define ATTRIBUTE_UNUSED __attribute__((unused)) # else # define ATTRIBUTE_UNUSED # endif #endif /** * LIBXML_ATTR_ALLOC_SIZE: * * Macro used to indicate to GCC this is an allocator function */ #ifndef LIBXML_ATTR_ALLOC_SIZE # if (!defined(__clang__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)))) # define LIBXML_ATTR_ALLOC_SIZE(x) __attribute__((alloc_size(x))) # else # define LIBXML_ATTR_ALLOC_SIZE(x) # endif #else # define LIBXML_ATTR_ALLOC_SIZE(x) #endif /** * LIBXML_ATTR_FORMAT: * * Macro used to indicate to GCC the parameter are printf like */ #ifndef LIBXML_ATTR_FORMAT # if ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3))) # define LIBXML_ATTR_FORMAT(fmt,args) __attribute__((__format__(__printf__,fmt,args))) # else # define LIBXML_ATTR_FORMAT(fmt,args) # endif #else # define LIBXML_ATTR_FORMAT(fmt,args) #endif #else /* ! __GNUC__ */ /** * ATTRIBUTE_UNUSED: * * Macro used to signal to GCC unused function parameters */ #define ATTRIBUTE_UNUSED /** * LIBXML_ATTR_ALLOC_SIZE: * * Macro used to indicate to GCC this is an allocator function */ #define LIBXML_ATTR_ALLOC_SIZE(x) /** * LIBXML_ATTR_FORMAT: * * Macro used to indicate to GCC the parameter are printf like */ #define LIBXML_ATTR_FORMAT(fmt,args) #endif /* __GNUC__ */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif PK!8KJɏɏlibxml/xmlerror.hnu[/* * Summary: error handling * Description: the API used to report errors * * Copy: See Copyright for the status of this software. * * Author: Daniel Veillard */ #include #ifndef __XML_ERROR_H__ #define __XML_ERROR_H__ #ifdef __cplusplus extern "C" { #endif /** * xmlErrorLevel: * * Indicates the level of an error */ typedef enum { XML_ERR_NONE = 0, XML_ERR_WARNING = 1, /* A simple warning */ XML_ERR_ERROR = 2, /* A recoverable error */ XML_ERR_FATAL = 3 /* A fatal error */ } xmlErrorLevel; /** * xmlErrorDomain: * * Indicates where an error may have come from */ typedef enum { XML_FROM_NONE = 0, XML_FROM_PARSER, /* The XML parser */ XML_FROM_TREE, /* The tree module */ XML_FROM_NAMESPACE, /* The XML Namespace module */ XML_FROM_DTD, /* The XML DTD validation with parser context*/ XML_FROM_HTML, /* The HTML parser */ XML_FROM_MEMORY, /* The memory allocator */ XML_FROM_OUTPUT, /* The serialization code */ XML_FROM_IO, /* The Input/Output stack */ XML_FROM_FTP, /* The FTP module */ XML_FROM_HTTP, /* The HTTP module */ XML_FROM_XINCLUDE, /* The XInclude processing */ XML_FROM_XPATH, /* The XPath module */ XML_FROM_XPOINTER, /* The XPointer module */ XML_FROM_REGEXP, /* The regular expressions module */ XML_FROM_DATATYPE, /* The W3C XML Schemas Datatype module */ XML_FROM_SCHEMASP, /* The W3C XML Schemas parser module */ XML_FROM_SCHEMASV, /* The W3C XML Schemas validation module */ XML_FROM_RELAXNGP, /* The Relax-NG parser module */ XML_FROM_RELAXNGV, /* The Relax-NG validator module */ XML_FROM_CATALOG, /* The Catalog module */ XML_FROM_C14N, /* The Canonicalization module */ XML_FROM_XSLT, /* The XSLT engine from libxslt */ XML_FROM_VALID, /* The XML DTD validation with valid context */ XML_FROM_CHECK, /* The error checking module */ XML_FROM_WRITER, /* The xmlwriter module */ XML_FROM_MODULE, /* The dynamically loaded module module*/ XML_FROM_I18N, /* The module handling character conversion */ XML_FROM_SCHEMATRONV,/* The Schematron validator module */ XML_FROM_BUFFER, /* The buffers module */ XML_FROM_URI /* The URI module */ } xmlErrorDomain; /** * xmlError: * * An XML Error instance. */ typedef struct _xmlError xmlError; typedef xmlError *xmlErrorPtr; struct _xmlError { int domain; /* What part of the library raised this error */ int code; /* The error code, e.g. an xmlParserError */ char *message;/* human-readable informative error message */ xmlErrorLevel level;/* how consequent is the error */ char *file; /* the filename */ int line; /* the line number if available */ char *str1; /* extra string information */ char *str2; /* extra string information */ char *str3; /* extra string information */ int int1; /* extra number information */ int int2; /* error column # or 0 if N/A (todo: rename field when we would brk ABI) */ void *ctxt; /* the parser context if available */ void *node; /* the node in the tree */ }; /** * xmlParserError: * * This is an error that the XML (or HTML) parser can generate */ typedef enum { XML_ERR_OK = 0, XML_ERR_INTERNAL_ERROR, /* 1 */ XML_ERR_NO_MEMORY, /* 2 */ XML_ERR_DOCUMENT_START, /* 3 */ XML_ERR_DOCUMENT_EMPTY, /* 4 */ XML_ERR_DOCUMENT_END, /* 5 */ XML_ERR_INVALID_HEX_CHARREF, /* 6 */ XML_ERR_INVALID_DEC_CHARREF, /* 7 */ XML_ERR_INVALID_CHARREF, /* 8 */ XML_ERR_INVALID_CHAR, /* 9 */ XML_ERR_CHARREF_AT_EOF, /* 10 */ XML_ERR_CHARREF_IN_PROLOG, /* 11 */ XML_ERR_CHARREF_IN_EPILOG, /* 12 */ XML_ERR_CHARREF_IN_DTD, /* 13 */ XML_ERR_ENTITYREF_AT_EOF, /* 14 */ XML_ERR_ENTITYREF_IN_PROLOG, /* 15 */ XML_ERR_ENTITYREF_IN_EPILOG, /* 16 */ XML_ERR_ENTITYREF_IN_DTD, /* 17 */ XML_ERR_PEREF_AT_EOF, /* 18 */ XML_ERR_PEREF_IN_PROLOG, /* 19 */ XML_ERR_PEREF_IN_EPILOG, /* 20 */ XML_ERR_PEREF_IN_INT_SUBSET, /* 21 */ XML_ERR_ENTITYREF_NO_NAME, /* 22 */ XML_ERR_ENTITYREF_SEMICOL_MISSING, /* 23 */ XML_ERR_PEREF_NO_NAME, /* 24 */ XML_ERR_PEREF_SEMICOL_MISSING, /* 25 */ XML_ERR_UNDECLARED_ENTITY, /* 26 */ XML_WAR_UNDECLARED_ENTITY, /* 27 */ XML_ERR_UNPARSED_ENTITY, /* 28 */ XML_ERR_ENTITY_IS_EXTERNAL, /* 29 */ XML_ERR_ENTITY_IS_PARAMETER, /* 30 */ XML_ERR_UNKNOWN_ENCODING, /* 31 */ XML_ERR_UNSUPPORTED_ENCODING, /* 32 */ XML_ERR_STRING_NOT_STARTED, /* 33 */ XML_ERR_STRING_NOT_CLOSED, /* 34 */ XML_ERR_NS_DECL_ERROR, /* 35 */ XML_ERR_ENTITY_NOT_STARTED, /* 36 */ XML_ERR_ENTITY_NOT_FINISHED, /* 37 */ XML_ERR_LT_IN_ATTRIBUTE, /* 38 */ XML_ERR_ATTRIBUTE_NOT_STARTED, /* 39 */ XML_ERR_ATTRIBUTE_NOT_FINISHED, /* 40 */ XML_ERR_ATTRIBUTE_WITHOUT_VALUE, /* 41 */ XML_ERR_ATTRIBUTE_REDEFINED, /* 42 */ XML_ERR_LITERAL_NOT_STARTED, /* 43 */ XML_ERR_LITERAL_NOT_FINISHED, /* 44 */ XML_ERR_COMMENT_NOT_FINISHED, /* 45 */ XML_ERR_PI_NOT_STARTED, /* 46 */ XML_ERR_PI_NOT_FINISHED, /* 47 */ XML_ERR_NOTATION_NOT_STARTED, /* 48 */ XML_ERR_NOTATION_NOT_FINISHED, /* 49 */ XML_ERR_ATTLIST_NOT_STARTED, /* 50 */ XML_ERR_ATTLIST_NOT_FINISHED, /* 51 */ XML_ERR_MIXED_NOT_STARTED, /* 52 */ XML_ERR_MIXED_NOT_FINISHED, /* 53 */ XML_ERR_ELEMCONTENT_NOT_STARTED, /* 54 */ XML_ERR_ELEMCONTENT_NOT_FINISHED, /* 55 */ XML_ERR_XMLDECL_NOT_STARTED, /* 56 */ XML_ERR_XMLDECL_NOT_FINISHED, /* 57 */ XML_ERR_CONDSEC_NOT_STARTED, /* 58 */ XML_ERR_CONDSEC_NOT_FINISHED, /* 59 */ XML_ERR_EXT_SUBSET_NOT_FINISHED, /* 60 */ XML_ERR_DOCTYPE_NOT_FINISHED, /* 61 */ XML_ERR_MISPLACED_CDATA_END, /* 62 */ XML_ERR_CDATA_NOT_FINISHED, /* 63 */ XML_ERR_RESERVED_XML_NAME, /* 64 */ XML_ERR_SPACE_REQUIRED, /* 65 */ XML_ERR_SEPARATOR_REQUIRED, /* 66 */ XML_ERR_NMTOKEN_REQUIRED, /* 67 */ XML_ERR_NAME_REQUIRED, /* 68 */ XML_ERR_PCDATA_REQUIRED, /* 69 */ XML_ERR_URI_REQUIRED, /* 70 */ XML_ERR_PUBID_REQUIRED, /* 71 */ XML_ERR_LT_REQUIRED, /* 72 */ XML_ERR_GT_REQUIRED, /* 73 */ XML_ERR_LTSLASH_REQUIRED, /* 74 */ XML_ERR_EQUAL_REQUIRED, /* 75 */ XML_ERR_TAG_NAME_MISMATCH, /* 76 */ XML_ERR_TAG_NOT_FINISHED, /* 77 */ XML_ERR_STANDALONE_VALUE, /* 78 */ XML_ERR_ENCODING_NAME, /* 79 */ XML_ERR_HYPHEN_IN_COMMENT, /* 80 */ XML_ERR_INVALID_ENCODING, /* 81 */ XML_ERR_EXT_ENTITY_STANDALONE, /* 82 */ XML_ERR_CONDSEC_INVALID, /* 83 */ XML_ERR_VALUE_REQUIRED, /* 84 */ XML_ERR_NOT_WELL_BALANCED, /* 85 */ XML_ERR_EXTRA_CONTENT, /* 86 */ XML_ERR_ENTITY_CHAR_ERROR, /* 87 */ XML_ERR_ENTITY_PE_INTERNAL, /* 88 */ XML_ERR_ENTITY_LOOP, /* 89 */ XML_ERR_ENTITY_BOUNDARY, /* 90 */ XML_ERR_INVALID_URI, /* 91 */ XML_ERR_URI_FRAGMENT, /* 92 */ XML_WAR_CATALOG_PI, /* 93 */ XML_ERR_NO_DTD, /* 94 */ XML_ERR_CONDSEC_INVALID_KEYWORD, /* 95 */ XML_ERR_VERSION_MISSING, /* 96 */ XML_WAR_UNKNOWN_VERSION, /* 97 */ XML_WAR_LANG_VALUE, /* 98 */ XML_WAR_NS_URI, /* 99 */ XML_WAR_NS_URI_RELATIVE, /* 100 */ XML_ERR_MISSING_ENCODING, /* 101 */ XML_WAR_SPACE_VALUE, /* 102 */ XML_ERR_NOT_STANDALONE, /* 103 */ XML_ERR_ENTITY_PROCESSING, /* 104 */ XML_ERR_NOTATION_PROCESSING, /* 105 */ XML_WAR_NS_COLUMN, /* 106 */ XML_WAR_ENTITY_REDEFINED, /* 107 */ XML_ERR_UNKNOWN_VERSION, /* 108 */ XML_ERR_VERSION_MISMATCH, /* 109 */ XML_ERR_NAME_TOO_LONG, /* 110 */ XML_ERR_USER_STOP, /* 111 */ XML_NS_ERR_XML_NAMESPACE = 200, XML_NS_ERR_UNDEFINED_NAMESPACE, /* 201 */ XML_NS_ERR_QNAME, /* 202 */ XML_NS_ERR_ATTRIBUTE_REDEFINED, /* 203 */ XML_NS_ERR_EMPTY, /* 204 */ XML_NS_ERR_COLON, /* 205 */ XML_DTD_ATTRIBUTE_DEFAULT = 500, XML_DTD_ATTRIBUTE_REDEFINED, /* 501 */ XML_DTD_ATTRIBUTE_VALUE, /* 502 */ XML_DTD_CONTENT_ERROR, /* 503 */ XML_DTD_CONTENT_MODEL, /* 504 */ XML_DTD_CONTENT_NOT_DETERMINIST, /* 505 */ XML_DTD_DIFFERENT_PREFIX, /* 506 */ XML_DTD_ELEM_DEFAULT_NAMESPACE, /* 507 */ XML_DTD_ELEM_NAMESPACE, /* 508 */ XML_DTD_ELEM_REDEFINED, /* 509 */ XML_DTD_EMPTY_NOTATION, /* 510 */ XML_DTD_ENTITY_TYPE, /* 511 */ XML_DTD_ID_FIXED, /* 512 */ XML_DTD_ID_REDEFINED, /* 513 */ XML_DTD_ID_SUBSET, /* 514 */ XML_DTD_INVALID_CHILD, /* 515 */ XML_DTD_INVALID_DEFAULT, /* 516 */ XML_DTD_LOAD_ERROR, /* 517 */ XML_DTD_MISSING_ATTRIBUTE, /* 518 */ XML_DTD_MIXED_CORRUPT, /* 519 */ XML_DTD_MULTIPLE_ID, /* 520 */ XML_DTD_NO_DOC, /* 521 */ XML_DTD_NO_DTD, /* 522 */ XML_DTD_NO_ELEM_NAME, /* 523 */ XML_DTD_NO_PREFIX, /* 524 */ XML_DTD_NO_ROOT, /* 525 */ XML_DTD_NOTATION_REDEFINED, /* 526 */ XML_DTD_NOTATION_VALUE, /* 527 */ XML_DTD_NOT_EMPTY, /* 528 */ XML_DTD_NOT_PCDATA, /* 529 */ XML_DTD_NOT_STANDALONE, /* 530 */ XML_DTD_ROOT_NAME, /* 531 */ XML_DTD_STANDALONE_WHITE_SPACE, /* 532 */ XML_DTD_UNKNOWN_ATTRIBUTE, /* 533 */ XML_DTD_UNKNOWN_ELEM, /* 534 */ XML_DTD_UNKNOWN_ENTITY, /* 535 */ XML_DTD_UNKNOWN_ID, /* 536 */ XML_DTD_UNKNOWN_NOTATION, /* 537 */ XML_DTD_STANDALONE_DEFAULTED, /* 538 */ XML_DTD_XMLID_VALUE, /* 539 */ XML_DTD_XMLID_TYPE, /* 540 */ XML_DTD_DUP_TOKEN, /* 541 */ XML_HTML_STRUCURE_ERROR = 800, XML_HTML_UNKNOWN_TAG, /* 801 */ XML_RNGP_ANYNAME_ATTR_ANCESTOR = 1000, XML_RNGP_ATTR_CONFLICT, /* 1001 */ XML_RNGP_ATTRIBUTE_CHILDREN, /* 1002 */ XML_RNGP_ATTRIBUTE_CONTENT, /* 1003 */ XML_RNGP_ATTRIBUTE_EMPTY, /* 1004 */ XML_RNGP_ATTRIBUTE_NOOP, /* 1005 */ XML_RNGP_CHOICE_CONTENT, /* 1006 */ XML_RNGP_CHOICE_EMPTY, /* 1007 */ XML_RNGP_CREATE_FAILURE, /* 1008 */ XML_RNGP_DATA_CONTENT, /* 1009 */ XML_RNGP_DEF_CHOICE_AND_INTERLEAVE, /* 1010 */ XML_RNGP_DEFINE_CREATE_FAILED, /* 1011 */ XML_RNGP_DEFINE_EMPTY, /* 1012 */ XML_RNGP_DEFINE_MISSING, /* 1013 */ XML_RNGP_DEFINE_NAME_MISSING, /* 1014 */ XML_RNGP_ELEM_CONTENT_EMPTY, /* 1015 */ XML_RNGP_ELEM_CONTENT_ERROR, /* 1016 */ XML_RNGP_ELEMENT_EMPTY, /* 1017 */ XML_RNGP_ELEMENT_CONTENT, /* 1018 */ XML_RNGP_ELEMENT_NAME, /* 1019 */ XML_RNGP_ELEMENT_NO_CONTENT, /* 1020 */ XML_RNGP_ELEM_TEXT_CONFLICT, /* 1021 */ XML_RNGP_EMPTY, /* 1022 */ XML_RNGP_EMPTY_CONSTRUCT, /* 1023 */ XML_RNGP_EMPTY_CONTENT, /* 1024 */ XML_RNGP_EMPTY_NOT_EMPTY, /* 1025 */ XML_RNGP_ERROR_TYPE_LIB, /* 1026 */ XML_RNGP_EXCEPT_EMPTY, /* 1027 */ XML_RNGP_EXCEPT_MISSING, /* 1028 */ XML_RNGP_EXCEPT_MULTIPLE, /* 1029 */ XML_RNGP_EXCEPT_NO_CONTENT, /* 1030 */ XML_RNGP_EXTERNALREF_EMTPY, /* 1031 */ XML_RNGP_EXTERNAL_REF_FAILURE, /* 1032 */ XML_RNGP_EXTERNALREF_RECURSE, /* 1033 */ XML_RNGP_FORBIDDEN_ATTRIBUTE, /* 1034 */ XML_RNGP_FOREIGN_ELEMENT, /* 1035 */ XML_RNGP_GRAMMAR_CONTENT, /* 1036 */ XML_RNGP_GRAMMAR_EMPTY, /* 1037 */ XML_RNGP_GRAMMAR_MISSING, /* 1038 */ XML_RNGP_GRAMMAR_NO_START, /* 1039 */ XML_RNGP_GROUP_ATTR_CONFLICT, /* 1040 */ XML_RNGP_HREF_ERROR, /* 1041 */ XML_RNGP_INCLUDE_EMPTY, /* 1042 */ XML_RNGP_INCLUDE_FAILURE, /* 1043 */ XML_RNGP_INCLUDE_RECURSE, /* 1044 */ XML_RNGP_INTERLEAVE_ADD, /* 1045 */ XML_RNGP_INTERLEAVE_CREATE_FAILED, /* 1046 */ XML_RNGP_INTERLEAVE_EMPTY, /* 1047 */ XML_RNGP_INTERLEAVE_NO_CONTENT, /* 1048 */ XML_RNGP_INVALID_DEFINE_NAME, /* 1049 */ XML_RNGP_INVALID_URI, /* 1050 */ XML_RNGP_INVALID_VALUE, /* 1051 */ XML_RNGP_MISSING_HREF, /* 1052 */ XML_RNGP_NAME_MISSING, /* 1053 */ XML_RNGP_NEED_COMBINE, /* 1054 */ XML_RNGP_NOTALLOWED_NOT_EMPTY, /* 1055 */ XML_RNGP_NSNAME_ATTR_ANCESTOR, /* 1056 */ XML_RNGP_NSNAME_NO_NS, /* 1057 */ XML_RNGP_PARAM_FORBIDDEN, /* 1058 */ XML_RNGP_PARAM_NAME_MISSING, /* 1059 */ XML_RNGP_PARENTREF_CREATE_FAILED, /* 1060 */ XML_RNGP_PARENTREF_NAME_INVALID, /* 1061 */ XML_RNGP_PARENTREF_NO_NAME, /* 1062 */ XML_RNGP_PARENTREF_NO_PARENT, /* 1063 */ XML_RNGP_PARENTREF_NOT_EMPTY, /* 1064 */ XML_RNGP_PARSE_ERROR, /* 1065 */ XML_RNGP_PAT_ANYNAME_EXCEPT_ANYNAME, /* 1066 */ XML_RNGP_PAT_ATTR_ATTR, /* 1067 */ XML_RNGP_PAT_ATTR_ELEM, /* 1068 */ XML_RNGP_PAT_DATA_EXCEPT_ATTR, /* 1069 */ XML_RNGP_PAT_DATA_EXCEPT_ELEM, /* 1070 */ XML_RNGP_PAT_DATA_EXCEPT_EMPTY, /* 1071 */ XML_RNGP_PAT_DATA_EXCEPT_GROUP, /* 1072 */ XML_RNGP_PAT_DATA_EXCEPT_INTERLEAVE, /* 1073 */ XML_RNGP_PAT_DATA_EXCEPT_LIST, /* 1074 */ XML_RNGP_PAT_DATA_EXCEPT_ONEMORE, /* 1075 */ XML_RNGP_PAT_DATA_EXCEPT_REF, /* 1076 */ XML_RNGP_PAT_DATA_EXCEPT_TEXT, /* 1077 */ XML_RNGP_PAT_LIST_ATTR, /* 1078 */ XML_RNGP_PAT_LIST_ELEM, /* 1079 */ XML_RNGP_PAT_LIST_INTERLEAVE, /* 1080 */ XML_RNGP_PAT_LIST_LIST, /* 1081 */ XML_RNGP_PAT_LIST_REF, /* 1082 */ XML_RNGP_PAT_LIST_TEXT, /* 1083 */ XML_RNGP_PAT_NSNAME_EXCEPT_ANYNAME, /* 1084 */ XML_RNGP_PAT_NSNAME_EXCEPT_NSNAME, /* 1085 */ XML_RNGP_PAT_ONEMORE_GROUP_ATTR, /* 1086 */ XML_RNGP_PAT_ONEMORE_INTERLEAVE_ATTR, /* 1087 */ XML_RNGP_PAT_START_ATTR, /* 1088 */ XML_RNGP_PAT_START_DATA, /* 1089 */ XML_RNGP_PAT_START_EMPTY, /* 1090 */ XML_RNGP_PAT_START_GROUP, /* 1091 */ XML_RNGP_PAT_START_INTERLEAVE, /* 1092 */ XML_RNGP_PAT_START_LIST, /* 1093 */ XML_RNGP_PAT_START_ONEMORE, /* 1094 */ XML_RNGP_PAT_START_TEXT, /* 1095 */ XML_RNGP_PAT_START_VALUE, /* 1096 */ XML_RNGP_PREFIX_UNDEFINED, /* 1097 */ XML_RNGP_REF_CREATE_FAILED, /* 1098 */ XML_RNGP_REF_CYCLE, /* 1099 */ XML_RNGP_REF_NAME_INVALID, /* 1100 */ XML_RNGP_REF_NO_DEF, /* 1101 */ XML_RNGP_REF_NO_NAME, /* 1102 */ XML_RNGP_REF_NOT_EMPTY, /* 1103 */ XML_RNGP_START_CHOICE_AND_INTERLEAVE, /* 1104 */ XML_RNGP_START_CONTENT, /* 1105 */ XML_RNGP_START_EMPTY, /* 1106 */ XML_RNGP_START_MISSING, /* 1107 */ XML_RNGP_TEXT_EXPECTED, /* 1108 */ XML_RNGP_TEXT_HAS_CHILD, /* 1109 */ XML_RNGP_TYPE_MISSING, /* 1110 */ XML_RNGP_TYPE_NOT_FOUND, /* 1111 */ XML_RNGP_TYPE_VALUE, /* 1112 */ XML_RNGP_UNKNOWN_ATTRIBUTE, /* 1113 */ XML_RNGP_UNKNOWN_COMBINE, /* 1114 */ XML_RNGP_UNKNOWN_CONSTRUCT, /* 1115 */ XML_RNGP_UNKNOWN_TYPE_LIB, /* 1116 */ XML_RNGP_URI_FRAGMENT, /* 1117 */ XML_RNGP_URI_NOT_ABSOLUTE, /* 1118 */ XML_RNGP_VALUE_EMPTY, /* 1119 */ XML_RNGP_VALUE_NO_CONTENT, /* 1120 */ XML_RNGP_XMLNS_NAME, /* 1121 */ XML_RNGP_XML_NS, /* 1122 */ XML_XPATH_EXPRESSION_OK = 1200, XML_XPATH_NUMBER_ERROR, /* 1201 */ XML_XPATH_UNFINISHED_LITERAL_ERROR, /* 1202 */ XML_XPATH_START_LITERAL_ERROR, /* 1203 */ XML_XPATH_VARIABLE_REF_ERROR, /* 1204 */ XML_XPATH_UNDEF_VARIABLE_ERROR, /* 1205 */ XML_XPATH_INVALID_PREDICATE_ERROR, /* 1206 */ XML_XPATH_EXPR_ERROR, /* 1207 */ XML_XPATH_UNCLOSED_ERROR, /* 1208 */ XML_XPATH_UNKNOWN_FUNC_ERROR, /* 1209 */ XML_XPATH_INVALID_OPERAND, /* 1210 */ XML_XPATH_INVALID_TYPE, /* 1211 */ XML_XPATH_INVALID_ARITY, /* 1212 */ XML_XPATH_INVALID_CTXT_SIZE, /* 1213 */ XML_XPATH_INVALID_CTXT_POSITION, /* 1214 */ XML_XPATH_MEMORY_ERROR, /* 1215 */ XML_XPTR_SYNTAX_ERROR, /* 1216 */ XML_XPTR_RESOURCE_ERROR, /* 1217 */ XML_XPTR_SUB_RESOURCE_ERROR, /* 1218 */ XML_XPATH_UNDEF_PREFIX_ERROR, /* 1219 */ XML_XPATH_ENCODING_ERROR, /* 1220 */ XML_XPATH_INVALID_CHAR_ERROR, /* 1221 */ XML_TREE_INVALID_HEX = 1300, XML_TREE_INVALID_DEC, /* 1301 */ XML_TREE_UNTERMINATED_ENTITY, /* 1302 */ XML_TREE_NOT_UTF8, /* 1303 */ XML_SAVE_NOT_UTF8 = 1400, XML_SAVE_CHAR_INVALID, /* 1401 */ XML_SAVE_NO_DOCTYPE, /* 1402 */ XML_SAVE_UNKNOWN_ENCODING, /* 1403 */ XML_REGEXP_COMPILE_ERROR = 1450, XML_IO_UNKNOWN = 1500, XML_IO_EACCES, /* 1501 */ XML_IO_EAGAIN, /* 1502 */ XML_IO_EBADF, /* 1503 */ XML_IO_EBADMSG, /* 1504 */ XML_IO_EBUSY, /* 1505 */ XML_IO_ECANCELED, /* 1506 */ XML_IO_ECHILD, /* 1507 */ XML_IO_EDEADLK, /* 1508 */ XML_IO_EDOM, /* 1509 */ XML_IO_EEXIST, /* 1510 */ XML_IO_EFAULT, /* 1511 */ XML_IO_EFBIG, /* 1512 */ XML_IO_EINPROGRESS, /* 1513 */ XML_IO_EINTR, /* 1514 */ XML_IO_EINVAL, /* 1515 */ XML_IO_EIO, /* 1516 */ XML_IO_EISDIR, /* 1517 */ XML_IO_EMFILE, /* 1518 */ XML_IO_EMLINK, /* 1519 */ XML_IO_EMSGSIZE, /* 1520 */ XML_IO_ENAMETOOLONG, /* 1521 */ XML_IO_ENFILE, /* 1522 */ XML_IO_ENODEV, /* 1523 */ XML_IO_ENOENT, /* 1524 */ XML_IO_ENOEXEC, /* 1525 */ XML_IO_ENOLCK, /* 1526 */ XML_IO_ENOMEM, /* 1527 */ XML_IO_ENOSPC, /* 1528 */ XML_IO_ENOSYS, /* 1529 */ XML_IO_ENOTDIR, /* 1530 */ XML_IO_ENOTEMPTY, /* 1531 */ XML_IO_ENOTSUP, /* 1532 */ XML_IO_ENOTTY, /* 1533 */ XML_IO_ENXIO, /* 1534 */ XML_IO_EPERM, /* 1535 */ XML_IO_EPIPE, /* 1536 */ XML_IO_ERANGE, /* 1537 */ XML_IO_EROFS, /* 1538 */ XML_IO_ESPIPE, /* 1539 */ XML_IO_ESRCH, /* 1540 */ XML_IO_ETIMEDOUT, /* 1541 */ XML_IO_EXDEV, /* 1542 */ XML_IO_NETWORK_ATTEMPT, /* 1543 */ XML_IO_ENCODER, /* 1544 */ XML_IO_FLUSH, /* 1545 */ XML_IO_WRITE, /* 1546 */ XML_IO_NO_INPUT, /* 1547 */ XML_IO_BUFFER_FULL, /* 1548 */ XML_IO_LOAD_ERROR, /* 1549 */ XML_IO_ENOTSOCK, /* 1550 */ XML_IO_EISCONN, /* 1551 */ XML_IO_ECONNREFUSED, /* 1552 */ XML_IO_ENETUNREACH, /* 1553 */ XML_IO_EADDRINUSE, /* 1554 */ XML_IO_EALREADY, /* 1555 */ XML_IO_EAFNOSUPPORT, /* 1556 */ XML_XINCLUDE_RECURSION=1600, XML_XINCLUDE_PARSE_VALUE, /* 1601 */ XML_XINCLUDE_ENTITY_DEF_MISMATCH, /* 1602 */ XML_XINCLUDE_NO_HREF, /* 1603 */ XML_XINCLUDE_NO_FALLBACK, /* 1604 */ XML_XINCLUDE_HREF_URI, /* 1605 */ XML_XINCLUDE_TEXT_FRAGMENT, /* 1606 */ XML_XINCLUDE_TEXT_DOCUMENT, /* 1607 */ XML_XINCLUDE_INVALID_CHAR, /* 1608 */ XML_XINCLUDE_BUILD_FAILED, /* 1609 */ XML_XINCLUDE_UNKNOWN_ENCODING, /* 1610 */ XML_XINCLUDE_MULTIPLE_ROOT, /* 1611 */ XML_XINCLUDE_XPTR_FAILED, /* 1612 */ XML_XINCLUDE_XPTR_RESULT, /* 1613 */ XML_XINCLUDE_INCLUDE_IN_INCLUDE, /* 1614 */ XML_XINCLUDE_FALLBACKS_IN_INCLUDE, /* 1615 */ XML_XINCLUDE_FALLBACK_NOT_IN_INCLUDE, /* 1616 */ XML_XINCLUDE_DEPRECATED_NS, /* 1617 */ XML_XINCLUDE_FRAGMENT_ID, /* 1618 */ XML_CATALOG_MISSING_ATTR = 1650, XML_CATALOG_ENTRY_BROKEN, /* 1651 */ XML_CATALOG_PREFER_VALUE, /* 1652 */ XML_CATALOG_NOT_CATALOG, /* 1653 */ XML_CATALOG_RECURSION, /* 1654 */ XML_SCHEMAP_PREFIX_UNDEFINED = 1700, XML_SCHEMAP_ATTRFORMDEFAULT_VALUE, /* 1701 */ XML_SCHEMAP_ATTRGRP_NONAME_NOREF, /* 1702 */ XML_SCHEMAP_ATTR_NONAME_NOREF, /* 1703 */ XML_SCHEMAP_COMPLEXTYPE_NONAME_NOREF, /* 1704 */ XML_SCHEMAP_ELEMFORMDEFAULT_VALUE, /* 1705 */ XML_SCHEMAP_ELEM_NONAME_NOREF, /* 1706 */ XML_SCHEMAP_EXTENSION_NO_BASE, /* 1707 */ XML_SCHEMAP_FACET_NO_VALUE, /* 1708 */ XML_SCHEMAP_FAILED_BUILD_IMPORT, /* 1709 */ XML_SCHEMAP_GROUP_NONAME_NOREF, /* 1710 */ XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI, /* 1711 */ XML_SCHEMAP_IMPORT_REDEFINE_NSNAME, /* 1712 */ XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI, /* 1713 */ XML_SCHEMAP_INVALID_BOOLEAN, /* 1714 */ XML_SCHEMAP_INVALID_ENUM, /* 1715 */ XML_SCHEMAP_INVALID_FACET, /* 1716 */ XML_SCHEMAP_INVALID_FACET_VALUE, /* 1717 */ XML_SCHEMAP_INVALID_MAXOCCURS, /* 1718 */ XML_SCHEMAP_INVALID_MINOCCURS, /* 1719 */ XML_SCHEMAP_INVALID_REF_AND_SUBTYPE, /* 1720 */ XML_SCHEMAP_INVALID_WHITE_SPACE, /* 1721 */ XML_SCHEMAP_NOATTR_NOREF, /* 1722 */ XML_SCHEMAP_NOTATION_NO_NAME, /* 1723 */ XML_SCHEMAP_NOTYPE_NOREF, /* 1724 */ XML_SCHEMAP_REF_AND_SUBTYPE, /* 1725 */ XML_SCHEMAP_RESTRICTION_NONAME_NOREF, /* 1726 */ XML_SCHEMAP_SIMPLETYPE_NONAME, /* 1727 */ XML_SCHEMAP_TYPE_AND_SUBTYPE, /* 1728 */ XML_SCHEMAP_UNKNOWN_ALL_CHILD, /* 1729 */ XML_SCHEMAP_UNKNOWN_ANYATTRIBUTE_CHILD, /* 1730 */ XML_SCHEMAP_UNKNOWN_ATTR_CHILD, /* 1731 */ XML_SCHEMAP_UNKNOWN_ATTRGRP_CHILD, /* 1732 */ XML_SCHEMAP_UNKNOWN_ATTRIBUTE_GROUP, /* 1733 */ XML_SCHEMAP_UNKNOWN_BASE_TYPE, /* 1734 */ XML_SCHEMAP_UNKNOWN_CHOICE_CHILD, /* 1735 */ XML_SCHEMAP_UNKNOWN_COMPLEXCONTENT_CHILD, /* 1736 */ XML_SCHEMAP_UNKNOWN_COMPLEXTYPE_CHILD, /* 1737 */ XML_SCHEMAP_UNKNOWN_ELEM_CHILD, /* 1738 */ XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD, /* 1739 */ XML_SCHEMAP_UNKNOWN_FACET_CHILD, /* 1740 */ XML_SCHEMAP_UNKNOWN_FACET_TYPE, /* 1741 */ XML_SCHEMAP_UNKNOWN_GROUP_CHILD, /* 1742 */ XML_SCHEMAP_UNKNOWN_IMPORT_CHILD, /* 1743 */ XML_SCHEMAP_UNKNOWN_LIST_CHILD, /* 1744 */ XML_SCHEMAP_UNKNOWN_NOTATION_CHILD, /* 1745 */ XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD, /* 1746 */ XML_SCHEMAP_UNKNOWN_REF, /* 1747 */ XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD, /* 1748 */ XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD, /* 1749 */ XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD, /* 1750 */ XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD, /* 1751 */ XML_SCHEMAP_UNKNOWN_SIMPLETYPE_CHILD, /* 1752 */ XML_SCHEMAP_UNKNOWN_TYPE, /* 1753 */ XML_SCHEMAP_UNKNOWN_UNION_CHILD, /* 1754 */ XML_SCHEMAP_ELEM_DEFAULT_FIXED, /* 1755 */ XML_SCHEMAP_REGEXP_INVALID, /* 1756 */ XML_SCHEMAP_FAILED_LOAD, /* 1757 */ XML_SCHEMAP_NOTHING_TO_PARSE, /* 1758 */ XML_SCHEMAP_NOROOT, /* 1759 */ XML_SCHEMAP_REDEFINED_GROUP, /* 1760 */ XML_SCHEMAP_REDEFINED_TYPE, /* 1761 */ XML_SCHEMAP_REDEFINED_ELEMENT, /* 1762 */ XML_SCHEMAP_REDEFINED_ATTRGROUP, /* 1763 */ XML_SCHEMAP_REDEFINED_ATTR, /* 1764 */ XML_SCHEMAP_REDEFINED_NOTATION, /* 1765 */ XML_SCHEMAP_FAILED_PARSE, /* 1766 */ XML_SCHEMAP_UNKNOWN_PREFIX, /* 1767 */ XML_SCHEMAP_DEF_AND_PREFIX, /* 1768 */ XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD, /* 1769 */ XML_SCHEMAP_INCLUDE_SCHEMA_NOT_URI, /* 1770 */ XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI, /* 1771 */ XML_SCHEMAP_NOT_SCHEMA, /* 1772 */ XML_SCHEMAP_UNKNOWN_MEMBER_TYPE, /* 1773 */ XML_SCHEMAP_INVALID_ATTR_USE, /* 1774 */ XML_SCHEMAP_RECURSIVE, /* 1775 */ XML_SCHEMAP_SUPERNUMEROUS_LIST_ITEM_TYPE, /* 1776 */ XML_SCHEMAP_INVALID_ATTR_COMBINATION, /* 1777 */ XML_SCHEMAP_INVALID_ATTR_INLINE_COMBINATION, /* 1778 */ XML_SCHEMAP_MISSING_SIMPLETYPE_CHILD, /* 1779 */ XML_SCHEMAP_INVALID_ATTR_NAME, /* 1780 */ XML_SCHEMAP_REF_AND_CONTENT, /* 1781 */ XML_SCHEMAP_CT_PROPS_CORRECT_1, /* 1782 */ XML_SCHEMAP_CT_PROPS_CORRECT_2, /* 1783 */ XML_SCHEMAP_CT_PROPS_CORRECT_3, /* 1784 */ XML_SCHEMAP_CT_PROPS_CORRECT_4, /* 1785 */ XML_SCHEMAP_CT_PROPS_CORRECT_5, /* 1786 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1, /* 1787 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1, /* 1788 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2, /* 1789 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2, /* 1790 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3, /* 1791 */ XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER, /* 1792 */ XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE, /* 1793 */ XML_SCHEMAP_UNION_NOT_EXPRESSIBLE, /* 1794 */ XML_SCHEMAP_SRC_IMPORT_3_1, /* 1795 */ XML_SCHEMAP_SRC_IMPORT_3_2, /* 1796 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1, /* 1797 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2, /* 1798 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3, /* 1799 */ XML_SCHEMAP_COS_CT_EXTENDS_1_3, /* 1800 */ XML_SCHEMAV_NOROOT = 1801, XML_SCHEMAV_UNDECLAREDELEM, /* 1802 */ XML_SCHEMAV_NOTTOPLEVEL, /* 1803 */ XML_SCHEMAV_MISSING, /* 1804 */ XML_SCHEMAV_WRONGELEM, /* 1805 */ XML_SCHEMAV_NOTYPE, /* 1806 */ XML_SCHEMAV_NOROLLBACK, /* 1807 */ XML_SCHEMAV_ISABSTRACT, /* 1808 */ XML_SCHEMAV_NOTEMPTY, /* 1809 */ XML_SCHEMAV_ELEMCONT, /* 1810 */ XML_SCHEMAV_HAVEDEFAULT, /* 1811 */ XML_SCHEMAV_NOTNILLABLE, /* 1812 */ XML_SCHEMAV_EXTRACONTENT, /* 1813 */ XML_SCHEMAV_INVALIDATTR, /* 1814 */ XML_SCHEMAV_INVALIDELEM, /* 1815 */ XML_SCHEMAV_NOTDETERMINIST, /* 1816 */ XML_SCHEMAV_CONSTRUCT, /* 1817 */ XML_SCHEMAV_INTERNAL, /* 1818 */ XML_SCHEMAV_NOTSIMPLE, /* 1819 */ XML_SCHEMAV_ATTRUNKNOWN, /* 1820 */ XML_SCHEMAV_ATTRINVALID, /* 1821 */ XML_SCHEMAV_VALUE, /* 1822 */ XML_SCHEMAV_FACET, /* 1823 */ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, /* 1824 */ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2, /* 1825 */ XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3, /* 1826 */ XML_SCHEMAV_CVC_TYPE_3_1_1, /* 1827 */ XML_SCHEMAV_CVC_TYPE_3_1_2, /* 1828 */ XML_SCHEMAV_CVC_FACET_VALID, /* 1829 */ XML_SCHEMAV_CVC_LENGTH_VALID, /* 1830 */ XML_SCHEMAV_CVC_MINLENGTH_VALID, /* 1831 */ XML_SCHEMAV_CVC_MAXLENGTH_VALID, /* 1832 */ XML_SCHEMAV_CVC_MININCLUSIVE_VALID, /* 1833 */ XML_SCHEMAV_CVC_MAXINCLUSIVE_VALID, /* 1834 */ XML_SCHEMAV_CVC_MINEXCLUSIVE_VALID, /* 1835 */ XML_SCHEMAV_CVC_MAXEXCLUSIVE_VALID, /* 1836 */ XML_SCHEMAV_CVC_TOTALDIGITS_VALID, /* 1837 */ XML_SCHEMAV_CVC_FRACTIONDIGITS_VALID, /* 1838 */ XML_SCHEMAV_CVC_PATTERN_VALID, /* 1839 */ XML_SCHEMAV_CVC_ENUMERATION_VALID, /* 1840 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, /* 1841 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2, /* 1842 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, /* 1843 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_2_4, /* 1844 */ XML_SCHEMAV_CVC_ELT_1, /* 1845 */ XML_SCHEMAV_CVC_ELT_2, /* 1846 */ XML_SCHEMAV_CVC_ELT_3_1, /* 1847 */ XML_SCHEMAV_CVC_ELT_3_2_1, /* 1848 */ XML_SCHEMAV_CVC_ELT_3_2_2, /* 1849 */ XML_SCHEMAV_CVC_ELT_4_1, /* 1850 */ XML_SCHEMAV_CVC_ELT_4_2, /* 1851 */ XML_SCHEMAV_CVC_ELT_4_3, /* 1852 */ XML_SCHEMAV_CVC_ELT_5_1_1, /* 1853 */ XML_SCHEMAV_CVC_ELT_5_1_2, /* 1854 */ XML_SCHEMAV_CVC_ELT_5_2_1, /* 1855 */ XML_SCHEMAV_CVC_ELT_5_2_2_1, /* 1856 */ XML_SCHEMAV_CVC_ELT_5_2_2_2_1, /* 1857 */ XML_SCHEMAV_CVC_ELT_5_2_2_2_2, /* 1858 */ XML_SCHEMAV_CVC_ELT_6, /* 1859 */ XML_SCHEMAV_CVC_ELT_7, /* 1860 */ XML_SCHEMAV_CVC_ATTRIBUTE_1, /* 1861 */ XML_SCHEMAV_CVC_ATTRIBUTE_2, /* 1862 */ XML_SCHEMAV_CVC_ATTRIBUTE_3, /* 1863 */ XML_SCHEMAV_CVC_ATTRIBUTE_4, /* 1864 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_3_1, /* 1865 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, /* 1866 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, /* 1867 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_4, /* 1868 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_5_1, /* 1869 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_5_2, /* 1870 */ XML_SCHEMAV_ELEMENT_CONTENT, /* 1871 */ XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING, /* 1872 */ XML_SCHEMAV_CVC_COMPLEX_TYPE_1, /* 1873 */ XML_SCHEMAV_CVC_AU, /* 1874 */ XML_SCHEMAV_CVC_TYPE_1, /* 1875 */ XML_SCHEMAV_CVC_TYPE_2, /* 1876 */ XML_SCHEMAV_CVC_IDC, /* 1877 */ XML_SCHEMAV_CVC_WILDCARD, /* 1878 */ XML_SCHEMAV_MISC, /* 1879 */ XML_XPTR_UNKNOWN_SCHEME = 1900, XML_XPTR_CHILDSEQ_START, /* 1901 */ XML_XPTR_EVAL_FAILED, /* 1902 */ XML_XPTR_EXTRA_OBJECTS, /* 1903 */ XML_C14N_CREATE_CTXT = 1950, XML_C14N_REQUIRES_UTF8, /* 1951 */ XML_C14N_CREATE_STACK, /* 1952 */ XML_C14N_INVALID_NODE, /* 1953 */ XML_C14N_UNKNOW_NODE, /* 1954 */ XML_C14N_RELATIVE_NAMESPACE, /* 1955 */ XML_FTP_PASV_ANSWER = 2000, XML_FTP_EPSV_ANSWER, /* 2001 */ XML_FTP_ACCNT, /* 2002 */ XML_FTP_URL_SYNTAX, /* 2003 */ XML_HTTP_URL_SYNTAX = 2020, XML_HTTP_USE_IP, /* 2021 */ XML_HTTP_UNKNOWN_HOST, /* 2022 */ XML_SCHEMAP_SRC_SIMPLE_TYPE_1 = 3000, XML_SCHEMAP_SRC_SIMPLE_TYPE_2, /* 3001 */ XML_SCHEMAP_SRC_SIMPLE_TYPE_3, /* 3002 */ XML_SCHEMAP_SRC_SIMPLE_TYPE_4, /* 3003 */ XML_SCHEMAP_SRC_RESOLVE, /* 3004 */ XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE, /* 3005 */ XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE, /* 3006 */ XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES, /* 3007 */ XML_SCHEMAP_ST_PROPS_CORRECT_1, /* 3008 */ XML_SCHEMAP_ST_PROPS_CORRECT_2, /* 3009 */ XML_SCHEMAP_ST_PROPS_CORRECT_3, /* 3010 */ XML_SCHEMAP_COS_ST_RESTRICTS_1_1, /* 3011 */ XML_SCHEMAP_COS_ST_RESTRICTS_1_2, /* 3012 */ XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1, /* 3013 */ XML_SCHEMAP_COS_ST_RESTRICTS_1_3_2, /* 3014 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_1, /* 3015 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1, /* 3016 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2, /* 3017 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1, /* 3018 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2, /* 3019 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3, /* 3020 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4, /* 3021 */ XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_5, /* 3022 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_1, /* 3023 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1, /* 3024 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2, /* 3025 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2, /* 3026 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1, /* 3027 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3, /* 3028 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4, /* 3029 */ XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_5, /* 3030 */ XML_SCHEMAP_COS_ST_DERIVED_OK_2_1, /* 3031 */ XML_SCHEMAP_COS_ST_DERIVED_OK_2_2, /* 3032 */ XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED, /* 3033 */ XML_SCHEMAP_S4S_ELEM_MISSING, /* 3034 */ XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, /* 3035 */ XML_SCHEMAP_S4S_ATTR_MISSING, /* 3036 */ XML_SCHEMAP_S4S_ATTR_INVALID_VALUE, /* 3037 */ XML_SCHEMAP_SRC_ELEMENT_1, /* 3038 */ XML_SCHEMAP_SRC_ELEMENT_2_1, /* 3039 */ XML_SCHEMAP_SRC_ELEMENT_2_2, /* 3040 */ XML_SCHEMAP_SRC_ELEMENT_3, /* 3041 */ XML_SCHEMAP_P_PROPS_CORRECT_1, /* 3042 */ XML_SCHEMAP_P_PROPS_CORRECT_2_1, /* 3043 */ XML_SCHEMAP_P_PROPS_CORRECT_2_2, /* 3044 */ XML_SCHEMAP_E_PROPS_CORRECT_2, /* 3045 */ XML_SCHEMAP_E_PROPS_CORRECT_3, /* 3046 */ XML_SCHEMAP_E_PROPS_CORRECT_4, /* 3047 */ XML_SCHEMAP_E_PROPS_CORRECT_5, /* 3048 */ XML_SCHEMAP_E_PROPS_CORRECT_6, /* 3049 */ XML_SCHEMAP_SRC_INCLUDE, /* 3050 */ XML_SCHEMAP_SRC_ATTRIBUTE_1, /* 3051 */ XML_SCHEMAP_SRC_ATTRIBUTE_2, /* 3052 */ XML_SCHEMAP_SRC_ATTRIBUTE_3_1, /* 3053 */ XML_SCHEMAP_SRC_ATTRIBUTE_3_2, /* 3054 */ XML_SCHEMAP_SRC_ATTRIBUTE_4, /* 3055 */ XML_SCHEMAP_NO_XMLNS, /* 3056 */ XML_SCHEMAP_NO_XSI, /* 3057 */ XML_SCHEMAP_COS_VALID_DEFAULT_1, /* 3058 */ XML_SCHEMAP_COS_VALID_DEFAULT_2_1, /* 3059 */ XML_SCHEMAP_COS_VALID_DEFAULT_2_2_1, /* 3060 */ XML_SCHEMAP_COS_VALID_DEFAULT_2_2_2, /* 3061 */ XML_SCHEMAP_CVC_SIMPLE_TYPE, /* 3062 */ XML_SCHEMAP_COS_CT_EXTENDS_1_1, /* 3063 */ XML_SCHEMAP_SRC_IMPORT_1_1, /* 3064 */ XML_SCHEMAP_SRC_IMPORT_1_2, /* 3065 */ XML_SCHEMAP_SRC_IMPORT_2, /* 3066 */ XML_SCHEMAP_SRC_IMPORT_2_1, /* 3067 */ XML_SCHEMAP_SRC_IMPORT_2_2, /* 3068 */ XML_SCHEMAP_INTERNAL, /* 3069 non-W3C */ XML_SCHEMAP_NOT_DETERMINISTIC, /* 3070 non-W3C */ XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_1, /* 3071 */ XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_2, /* 3072 */ XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3, /* 3073 */ XML_SCHEMAP_MG_PROPS_CORRECT_1, /* 3074 */ XML_SCHEMAP_MG_PROPS_CORRECT_2, /* 3075 */ XML_SCHEMAP_SRC_CT_1, /* 3076 */ XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3, /* 3077 */ XML_SCHEMAP_AU_PROPS_CORRECT_2, /* 3078 */ XML_SCHEMAP_A_PROPS_CORRECT_2, /* 3079 */ XML_SCHEMAP_C_PROPS_CORRECT, /* 3080 */ XML_SCHEMAP_SRC_REDEFINE, /* 3081 */ XML_SCHEMAP_SRC_IMPORT, /* 3082 */ XML_SCHEMAP_WARN_SKIP_SCHEMA, /* 3083 */ XML_SCHEMAP_WARN_UNLOCATED_SCHEMA, /* 3084 */ XML_SCHEMAP_WARN_ATTR_REDECL_PROH, /* 3085 */ XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH, /* 3085 */ XML_SCHEMAP_AG_PROPS_CORRECT, /* 3086 */ XML_SCHEMAP_COS_CT_EXTENDS_1_2, /* 3087 */ XML_SCHEMAP_AU_PROPS_CORRECT, /* 3088 */ XML_SCHEMAP_A_PROPS_CORRECT_3, /* 3089 */ XML_SCHEMAP_COS_ALL_LIMITED, /* 3090 */ XML_SCHEMATRONV_ASSERT = 4000, /* 4000 */ XML_SCHEMATRONV_REPORT, XML_MODULE_OPEN = 4900, /* 4900 */ XML_MODULE_CLOSE, /* 4901 */ XML_CHECK_FOUND_ELEMENT = 5000, XML_CHECK_FOUND_ATTRIBUTE, /* 5001 */ XML_CHECK_FOUND_TEXT, /* 5002 */ XML_CHECK_FOUND_CDATA, /* 5003 */ XML_CHECK_FOUND_ENTITYREF, /* 5004 */ XML_CHECK_FOUND_ENTITY, /* 5005 */ XML_CHECK_FOUND_PI, /* 5006 */ XML_CHECK_FOUND_COMMENT, /* 5007 */ XML_CHECK_FOUND_DOCTYPE, /* 5008 */ XML_CHECK_FOUND_FRAGMENT, /* 5009 */ XML_CHECK_FOUND_NOTATION, /* 5010 */ XML_CHECK_UNKNOWN_NODE, /* 5011 */ XML_CHECK_ENTITY_TYPE, /* 5012 */ XML_CHECK_NO_PARENT, /* 5013 */ XML_CHECK_NO_DOC, /* 5014 */ XML_CHECK_NO_NAME, /* 5015 */ XML_CHECK_NO_ELEM, /* 5016 */ XML_CHECK_WRONG_DOC, /* 5017 */ XML_CHECK_NO_PREV, /* 5018 */ XML_CHECK_WRONG_PREV, /* 5019 */ XML_CHECK_NO_NEXT, /* 5020 */ XML_CHECK_WRONG_NEXT, /* 5021 */ XML_CHECK_NOT_DTD, /* 5022 */ XML_CHECK_NOT_ATTR, /* 5023 */ XML_CHECK_NOT_ATTR_DECL, /* 5024 */ XML_CHECK_NOT_ELEM_DECL, /* 5025 */ XML_CHECK_NOT_ENTITY_DECL, /* 5026 */ XML_CHECK_NOT_NS_DECL, /* 5027 */ XML_CHECK_NO_HREF, /* 5028 */ XML_CHECK_WRONG_PARENT,/* 5029 */ XML_CHECK_NS_SCOPE, /* 5030 */ XML_CHECK_NS_ANCESTOR, /* 5031 */ XML_CHECK_NOT_UTF8, /* 5032 */ XML_CHECK_NO_DICT, /* 5033 */ XML_CHECK_NOT_NCNAME, /* 5034 */ XML_CHECK_OUTSIDE_DICT, /* 5035 */ XML_CHECK_WRONG_NAME, /* 5036 */ XML_CHECK_NAME_NOT_NULL, /* 5037 */ XML_I18N_NO_NAME = 6000, XML_I18N_NO_HANDLER, /* 6001 */ XML_I18N_EXCESS_HANDLER, /* 6002 */ XML_I18N_CONV_FAILED, /* 6003 */ XML_I18N_NO_OUTPUT, /* 6004 */ XML_BUF_OVERFLOW = 7000 } xmlParserErrors; /** * xmlGenericErrorFunc: * @ctx: a parsing context * @msg: the message * @...: the extra arguments of the varargs to format the message * * Signature of the function to use when there is an error and * no parsing or validity context available . */ typedef void (XMLCDECL *xmlGenericErrorFunc) (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); /** * xmlStructuredErrorFunc: * @userData: user provided data for the error callback * @error: the error being raised. * * Signature of the function to use when there is an error and * the module handles the new error reporting mechanism. */ typedef void (XMLCALL *xmlStructuredErrorFunc) (void *userData, xmlErrorPtr error); /* * Use the following function to reset the two global variables * xmlGenericError and xmlGenericErrorContext. */ XMLPUBFUN void XMLCALL xmlSetGenericErrorFunc (void *ctx, xmlGenericErrorFunc handler); XMLPUBFUN void XMLCALL initGenericErrorDefaultFunc (xmlGenericErrorFunc *handler); XMLPUBFUN void XMLCALL xmlSetStructuredErrorFunc (void *ctx, xmlStructuredErrorFunc handler); /* * Default message routines used by SAX and Valid context for error * and warning reporting. */ XMLPUBFUN void XMLCDECL xmlParserError (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN void XMLCDECL xmlParserWarning (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN void XMLCDECL xmlParserValidityError (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN void XMLCDECL xmlParserValidityWarning (void *ctx, const char *msg, ...) LIBXML_ATTR_FORMAT(2,3); XMLPUBFUN void XMLCALL xmlParserPrintFileInfo (xmlParserInputPtr input); XMLPUBFUN void XMLCALL xmlParserPrintFileContext (xmlParserInputPtr input); /* * Extended error information routines */ XMLPUBFUN xmlErrorPtr XMLCALL xmlGetLastError (void); XMLPUBFUN void XMLCALL xmlResetLastError (void); XMLPUBFUN xmlErrorPtr XMLCALL xmlCtxtGetLastError (void *ctx); XMLPUBFUN void XMLCALL xmlCtxtResetLastError (void *ctx); XMLPUBFUN void XMLCALL xmlResetError (xmlErrorPtr err); XMLPUBFUN int XMLCALL xmlCopyError (xmlErrorPtr from, xmlErrorPtr to); #ifdef IN_LIBXML /* * Internal callback reporting routine */ XMLPUBFUN void XMLCALL __xmlRaiseError (xmlStructuredErrorFunc schannel, xmlGenericErrorFunc channel, void *data, void *ctx, void *node, int domain, int code, xmlErrorLevel level, const char *file, int line, const char *str1, const char *str2, const char *str3, int int1, int col, const char *msg, ...) LIBXML_ATTR_FORMAT(16,17); XMLPUBFUN void XMLCALL __xmlSimpleError (int domain, int code, xmlNodePtr node, const char *msg, const char *extra) LIBXML_ATTR_FORMAT(4,0); #endif #ifdef __cplusplus } #endif #endif /* __XML_ERROR_H__ */ PK!#-- - libxml/c14n.hnu[/* * Summary: Provide Canonical XML and Exclusive XML Canonicalization * Description: the c14n modules provides a * * "Canonical XML" implementation * http://www.w3.org/TR/xml-c14n * * and an * * "Exclusive XML Canonicalization" implementation * http://www.w3.org/TR/xml-exc-c14n * Copy: See Copyright for the status of this software. * * Author: Aleksey Sanin */ #ifndef __XML_C14N_H__ #define __XML_C14N_H__ #include #ifdef LIBXML_C14N_ENABLED #ifdef LIBXML_OUTPUT_ENABLED #include #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* * XML Canonicalization * http://www.w3.org/TR/xml-c14n * * Exclusive XML Canonicalization * http://www.w3.org/TR/xml-exc-c14n * * Canonical form of an XML document could be created if and only if * a) default attributes (if any) are added to all nodes * b) all character and parsed entity references are resolved * In order to achieve this in libxml2 the document MUST be loaded with * following global settings: * * xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; * xmlSubstituteEntitiesDefault(1); * * or corresponding parser context setting: * xmlParserCtxtPtr ctxt; * * ... * ctxt->loadsubset = XML_DETECT_IDS | XML_COMPLETE_ATTRS; * ctxt->replaceEntities = 1; * ... */ /* * xmlC14NMode: * * Predefined values for C14N modes * */ typedef enum { XML_C14N_1_0 = 0, /* Original C14N 1.0 spec */ XML_C14N_EXCLUSIVE_1_0 = 1, /* Exclusive C14N 1.0 spec */ XML_C14N_1_1 = 2 /* C14N 1.1 spec */ } xmlC14NMode; XMLPUBFUN int XMLCALL xmlC14NDocSaveTo (xmlDocPtr doc, xmlNodeSetPtr nodes, int mode, /* a xmlC14NMode */ xmlChar **inclusive_ns_prefixes, int with_comments, xmlOutputBufferPtr buf); XMLPUBFUN int XMLCALL xmlC14NDocDumpMemory (xmlDocPtr doc, xmlNodeSetPtr nodes, int mode, /* a xmlC14NMode */ xmlChar **inclusive_ns_prefixes, int with_comments, xmlChar **doc_txt_ptr); XMLPUBFUN int XMLCALL xmlC14NDocSave (xmlDocPtr doc, xmlNodeSetPtr nodes, int mode, /* a xmlC14NMode */ xmlChar **inclusive_ns_prefixes, int with_comments, const char* filename, int compression); /** * This is the core C14N function */ /** * xmlC14NIsVisibleCallback: * @user_data: user data * @node: the current node * @parent: the parent node * * Signature for a C14N callback on visible nodes * * Returns 1 if the node should be included */ typedef int (*xmlC14NIsVisibleCallback) (void* user_data, xmlNodePtr node, xmlNodePtr parent); XMLPUBFUN int XMLCALL xmlC14NExecute (xmlDocPtr doc, xmlC14NIsVisibleCallback is_visible_callback, void* user_data, int mode, /* a xmlC14NMode */ xmlChar **inclusive_ns_prefixes, int with_comments, xmlOutputBufferPtr buf); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* LIBXML_OUTPUT_ENABLED */ #endif /* LIBXML_C14N_ENABLED */ #endif /* __XML_C14N_H__ */ PK!Cccc14n.pxdnu[from lxml.includes.tree cimport xmlDoc, xmlOutputBuffer, xmlChar from lxml.includes.xpath cimport xmlNodeSet cdef extern from "libxml/c14n.h": cdef int xmlC14NDocDumpMemory(xmlDoc* doc, xmlNodeSet* nodes, int exclusive, xmlChar** inclusive_ns_prefixes, int with_comments, xmlChar** doc_txt_ptr) nogil cdef int xmlC14NDocSave(xmlDoc* doc, xmlNodeSet* nodes, int exclusive, xmlChar** inclusive_ns_prefixes, int with_comments, char* filename, int compression) nogil cdef int xmlC14NDocSaveTo(xmlDoc* doc, xmlNodeSet* nodes, int exclusive, xmlChar** inclusive_ns_prefixes, int with_comments, xmlOutputBuffer* buffer) nogil PK!rP!''etreepublic.pxdnu[# public Cython/C interface to lxml.etree from lxml.includes cimport tree from lxml.includes.tree cimport const_xmlChar cdef extern from "lxml-version.h": cdef char* LXML_VERSION_STRING cdef extern from "etree_defs.h": # test if c_node is considered an Element (i.e. Element, Comment, etc.) cdef bint _isElement(tree.xmlNode* c_node) nogil # return the namespace URI of the node or NULL cdef const_xmlChar* _getNs(tree.xmlNode* node) nogil # pair of macros for tree traversal cdef void BEGIN_FOR_EACH_ELEMENT_FROM(tree.xmlNode* tree_top, tree.xmlNode* start_node, int start_node_inclusive) nogil cdef void END_FOR_EACH_ELEMENT_FROM(tree.xmlNode* start_node) nogil cdef extern from "etree_api.h": # first function to call! cdef int import_lxml__etree() except -1 ########################################################################## # public ElementTree API classes cdef class lxml.etree._Document [ object LxmlDocument ]: cdef tree.xmlDoc* _c_doc cdef class lxml.etree._Element [ object LxmlElement ]: cdef _Document _doc cdef tree.xmlNode* _c_node cdef class lxml.etree.ElementBase(_Element) [ object LxmlElementBase ]: pass cdef class lxml.etree._ElementTree [ object LxmlElementTree ]: cdef _Document _doc cdef _Element _context_node cdef class lxml.etree.ElementClassLookup [ object LxmlElementClassLookup ]: cdef object (*_lookup_function)(object, _Document, tree.xmlNode*) cdef class lxml.etree.FallbackElementClassLookup(ElementClassLookup) \ [ object LxmlFallbackElementClassLookup ]: cdef ElementClassLookup fallback cdef object (*_fallback_function)(object, _Document, tree.xmlNode*) ########################################################################## # creating Element objects # create an Element for a C-node in the Document cdef _Element elementFactory(_Document doc, tree.xmlNode* c_node) # create an ElementTree for an Element cdef _ElementTree elementTreeFactory(_Element context_node) # create an ElementTree subclass for an Element cdef _ElementTree newElementTree(_Element context_node, object subclass) # create an ElementTree from an external document cdef _ElementTree adoptExternalDocument(tree.xmlDoc* c_doc, parser, bint is_owned) # create a new Element for an existing or new document (doc = None) # builds Python object after setting text, tail, namespaces and attributes cdef _Element makeElement(tag, _Document doc, parser, text, tail, attrib, nsmap) # create a new SubElement for an existing parent # builds Python object after setting text, tail, namespaces and attributes cdef _Element makeSubElement(_Element parent, tag, text, tail, attrib, nsmap) # deep copy a node to include it in the Document cdef _Element deepcopyNodeToDocument(_Document doc, tree.xmlNode* c_root) # set the internal lookup function for Element/Comment/PI classes # use setElementClassLookupFunction(NULL, None) to reset it # note that the lookup function *must always* return an _Element subclass! cdef void setElementClassLookupFunction( object (*function)(object, _Document, tree.xmlNode*), object state) # lookup function that always returns the default Element class # note that the first argument is expected to be None! cdef object lookupDefaultElementClass(_1, _Document _2, tree.xmlNode* c_node) # lookup function for namespace/tag specific Element classes # note that the first argument is expected to be None! cdef object lookupNamespaceElementClass(_1, _Document _2, tree.xmlNode* c_node) # call the fallback lookup function of a FallbackElementClassLookup cdef object callLookupFallback(FallbackElementClassLookup lookup, _Document doc, tree.xmlNode* c_node) ########################################################################## # XML attribute access # return an attribute value for a C attribute on a C element node cdef object attributeValue(tree.xmlNode* c_element, tree.xmlAttr* c_attrib_node) # return the value of the attribute with 'ns' and 'name' (or None) cdef object attributeValueFromNsName(tree.xmlNode* c_element, const_xmlChar* c_ns, const_xmlChar* c_name) # return the value of attribute "{ns}name", or the default value cdef object getAttributeValue(_Element element, key, default) # return an iterator over attribute names (1), values (2) or items (3) # attributes must not be removed during iteration! cdef object iterattributes(_Element element, int keysvalues) # return the list of all attribute names (1), values (2) or items (3) cdef list collectAttributes(tree.xmlNode* c_element, int keysvalues) # set an attribute value on an element # on failure, sets an exception and returns -1 cdef int setAttributeValue(_Element element, key, value) except -1 # delete an attribute # on failure, sets an exception and returns -1 cdef int delAttribute(_Element element, key) except -1 # delete an attribute based on name and namespace URI # returns -1 if the attribute was not found (no exception) cdef int delAttributeFromNsName(tree.xmlNode* c_element, const_xmlChar* c_href, const_xmlChar* c_name) ########################################################################## # XML node helper functions # check if the element has at least one child cdef bint hasChild(tree.xmlNode* c_node) nogil # find child element number 'index' (supports negative indexes) cdef tree.xmlNode* findChild(tree.xmlNode* c_node, Py_ssize_t index) nogil # find child element number 'index' starting at first one cdef tree.xmlNode* findChildForwards(tree.xmlNode* c_node, Py_ssize_t index) nogil # find child element number 'index' starting at last one cdef tree.xmlNode* findChildBackwards(tree.xmlNode* c_node, Py_ssize_t index) nogil # return next/previous sibling element of the node cdef tree.xmlNode* nextElement(tree.xmlNode* c_node) nogil cdef tree.xmlNode* previousElement(tree.xmlNode* c_node) nogil ########################################################################## # iterators (DEPRECATED API, don't use in new code!) cdef class lxml.etree._ElementTagMatcher [ object LxmlElementTagMatcher ]: cdef char* _href cdef char* _name # store "{ns}tag" (or None) filter for this matcher or element iterator # ** unless _href *and* _name are set up 'by hand', this function *must* # ** be called when subclassing the iterator below! cdef void initTagMatch(_ElementTagMatcher matcher, tag) cdef class lxml.etree._ElementIterator(_ElementTagMatcher) [ object LxmlElementIterator ]: cdef _Element _node cdef tree.xmlNode* (*_next_element)(tree.xmlNode*) # store the initial node of the iterator if it matches the required tag # or its next matching sibling if not cdef void iteratorStoreNext(_ElementIterator iterator, _Element node) ########################################################################## # other helper functions # check if a C node matches a tag name and namespace # (NULL allowed for each => always matches) cdef int tagMatches(tree.xmlNode* c_node, const_xmlChar* c_href, const_xmlChar* c_name) # convert a UTF-8 char* to a Python string or unicode string cdef object pyunicode(const_xmlChar* s) # convert the string to UTF-8 using the normal lxml.etree semantics cdef bytes utf8(object s) # split a tag into a (URI, name) tuple, return None as URI for '{}tag' cdef tuple getNsTag(object tag) # split a tag into a (URI, name) tuple, return b'' as URI for '{}tag' cdef tuple getNsTagWithEmptyNs(object tag) # get the "{ns}tag" string for a C node cdef object namespacedName(tree.xmlNode* c_node) # get the "{ns}tag" string for a href/tagname pair (c_ns may be NULL) cdef object namespacedNameFromNsName(const_xmlChar* c_ns, const_xmlChar* c_tag) # check if the node has a text value (which may be '') cdef bint hasText(tree.xmlNode* c_node) nogil # check if the node has a tail value (which may be '') cdef bint hasTail(tree.xmlNode* c_node) nogil # get the text content of an element (or None) cdef object textOf(tree.xmlNode* c_node) # get the tail content of an element (or None) cdef object tailOf(tree.xmlNode* c_node) # set the text value of an element cdef int setNodeText(tree.xmlNode* c_node, text) except -1 # set the tail text value of an element cdef int setTailText(tree.xmlNode* c_node, text) except -1 # append an element to the children of a parent element # deprecated: don't use, does not propagate exceptions! # use appendChildToElement() instead cdef void appendChild(_Element parent, _Element child) # added in lxml 3.3 as a safe replacement for appendChild() # return -1 for exception, 0 for ok cdef int appendChildToElement(_Element parent, _Element child) except -1 # recursively lookup a namespace in element or ancestors, or create it cdef tree.xmlNs* findOrBuildNodeNsPrefix( _Document doc, tree.xmlNode* c_node, const_xmlChar* href, const_xmlChar* prefix) # find the Document of an Element, ElementTree or Document (itself!) cdef _Document documentOrRaise(object input) # find the root Element of an Element (itself!), ElementTree or Document cdef _Element rootNodeOrRaise(object input) PK! __init__.pynu[PK!Suri.pxdnu[cdef extern from "libxml/uri.h": ctypedef struct xmlURI cdef xmlURI* xmlParseURI(char* str) cdef void xmlFreeURI(xmlURI* uri) PK!x|4 4 htmlparser.pxdnu[from libc.string cimport const_char from lxml.includes.tree cimport xmlDoc from lxml.includes.tree cimport xmlInputReadCallback, xmlInputCloseCallback from lxml.includes.xmlparser cimport xmlParserCtxt, xmlSAXHandler, xmlSAXHandlerV1 cdef extern from "libxml/HTMLparser.h": ctypedef enum htmlParserOption: HTML_PARSE_NOERROR # suppress error reports HTML_PARSE_NOWARNING # suppress warning reports HTML_PARSE_PEDANTIC # pedantic error reporting HTML_PARSE_NOBLANKS # remove blank nodes HTML_PARSE_NONET # Forbid network access # libxml2 2.6.21+ only: HTML_PARSE_RECOVER # Relaxed parsing HTML_PARSE_COMPACT # compact small text nodes # libxml2 2.7.7+ only: HTML_PARSE_NOIMPLIED # Do not add implied html/body... elements # libxml2 2.7.8+ only: HTML_PARSE_NODEFDTD # do not default a doctype if not found # libxml2 2.8.0+ only: XML_PARSE_IGNORE_ENC # ignore internal document encoding hint xmlSAXHandlerV1 htmlDefaultSAXHandler cdef xmlParserCtxt* htmlCreateMemoryParserCtxt( char* buffer, int size) nogil cdef xmlParserCtxt* htmlCreateFileParserCtxt( char* filename, char* encoding) nogil cdef xmlParserCtxt* htmlCreatePushParserCtxt(xmlSAXHandler* sax, void* user_data, char* chunk, int size, char* filename, int enc) nogil cdef void htmlFreeParserCtxt(xmlParserCtxt* ctxt) nogil cdef void htmlCtxtReset(xmlParserCtxt* ctxt) nogil cdef int htmlCtxtUseOptions(xmlParserCtxt* ctxt, int options) nogil cdef int htmlParseDocument(xmlParserCtxt* ctxt) nogil cdef int htmlParseChunk(xmlParserCtxt* ctxt, char* chunk, int size, int terminate) nogil cdef xmlDoc* htmlCtxtReadFile(xmlParserCtxt* ctxt, char* filename, const_char* encoding, int options) nogil cdef xmlDoc* htmlCtxtReadDoc(xmlParserCtxt* ctxt, char* buffer, char* URL, const_char* encoding, int options) nogil cdef xmlDoc* htmlCtxtReadIO(xmlParserCtxt* ctxt, xmlInputReadCallback ioread, xmlInputCloseCallback ioclose, void* ioctx, char* URL, const_char* encoding, int options) nogil cdef xmlDoc* htmlCtxtReadMemory(xmlParserCtxt* ctxt, char* buffer, int size, char* filename, const_char* encoding, int options) nogil PK!AЅ==class-ajax.phpnu[post_type_object ) { $this->post_type_object = get_post_type_object( 'docs' ); } return $this->post_type_object; } /** * Get post data to use in Vue. * * @param object $post - post data. * * @return array */ public function get_post_data( $post ) { $cat_id = 0; $cat_name = ''; // get category. $terms = wp_get_post_terms( $post->ID, 'docs_category' ); if ( ! empty( $terms ) && isset( $terms[0] ) ) { $cat_id = $terms[0]->term_id; $cat_name = $terms[0]->name; } return array( 'id' => $post->ID, 'title' => $post->post_title, 'name' => $post->post_name, 'status' => $post->post_status, 'thumb' => get_the_post_thumbnail_url( $post, 'documentor_archive_sm' ), 'order' => $post->menu_order, 'cat_id' => $cat_id, 'cat_name' => $cat_name, 'caps' => array( 'edit' => current_user_can( $this->get_post_type_object()->cap->edit_post, $post->ID ), 'delete' => current_user_can( $this->get_post_type_object()->cap->delete_post, $post->ID ), ), ); } /** * Create a new doc * * @return void */ public function create_doc() { check_ajax_referer( 'documentor-admin-nonce' ); $title = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : ''; $status = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : 'publish'; $parent = isset( $_POST['parent'] ) ? absint( $_POST['parent'] ) : 0; $order = isset( $_POST['order'] ) ? absint( $_POST['order'] ) : 0; if ( ! current_user_can( $this->get_post_type_object()->cap->publish_posts ) ) { $status = 'pending'; } $post_id = wp_insert_post( array( 'post_title' => $title, 'post_type' => 'docs', 'post_status' => $status, 'post_parent' => $parent, 'post_author' => get_current_user_id(), 'menu_order' => $order, ) ); if ( is_wp_error( $post_id ) ) { wp_send_json_error(); } $post = get_post( $post_id ); wp_send_json_success( array( 'post' => $this->get_post_data( $post ), 'child' => array(), ) ); } /** * Clone a doc * * @return void */ public function clone_doc() { check_ajax_referer( 'documentor-admin-nonce' ); $title = isset( $_POST['title'] ) ? sanitize_text_field( wp_unslash( $_POST['title'] ) ) : ''; $clone_from = isset( $_POST['clone_from'] ) ? absint( $_POST['clone_from'] ) : 0; $result = array(); if ( $clone_from ) { $clone_from_post = get_post( $clone_from ); if ( is_wp_error( $clone_from_post ) ) { wp_send_json_error(); } $clone_post_meta = get_post_custom( $clone_from_post->ID ); $new_post_id = wp_insert_post( array( 'post_title' => $title, 'post_type' => 'docs', 'post_status' => 'publish', 'post_content' => $clone_from_post->post_content, 'post_content_filtered' => $clone_from_post->post_content_filtered, 'post_excerpt' => $clone_from_post->post_excerpt, 'post_author' => get_current_user_id(), 'comment_status' => $clone_from_post->comment_status, 'ping_status' => $clone_from_post->ping_status, 'to_ping' => $clone_from_post->to_ping, ) ); if ( is_wp_error( $new_post_id ) ) { wp_send_json_error(); } // Copy post metadata. foreach ( $clone_post_meta as $key => $values ) { if ( 'positive' === $key || 'negative' === $key ) { continue; } foreach ( $values as $value ) { add_post_meta( $new_post_id, $key, $value ); } } $new_post = get_post( $new_post_id ); $result = array( 'post' => $this->get_post_data( $new_post ), 'child' => $this->clone_child_docs( $clone_from_post->ID, $new_post_id ), ); } wp_send_json_success( $result ); } /** * Clone child docs. * * @param int $clone_from - post id. * @param int $clone_to - post id. * * @return array */ public function clone_child_docs( $clone_from, $clone_to ) { $childrens = new WP_Query( array( 'post_type' => 'docs', 'posts_per_page' => -1, // phpcs:ignore 'post_parent' => $clone_from, 'orderby' => array( 'menu_order' => 'ASC', 'date' => 'DESC', ), ) ); $result = array(); while ( $childrens->have_posts() ) : $childrens->the_post(); $clone_from_post = $childrens->post; if ( is_wp_error( $clone_from_post ) ) { wp_send_json_error(); } $clone_post_meta = get_post_custom( $clone_from_post->ID ); $new_post_id = wp_insert_post( array( 'post_title' => $clone_from_post->post_title, 'post_type' => $clone_from_post->post_type, 'post_status' => $clone_from_post->post_status, 'post_content' => $clone_from_post->post_content, 'post_content_filtered' => $clone_from_post->post_content_filtered, 'post_excerpt' => $clone_from_post->post_excerpt, 'post_author' => get_current_user_id(), 'post_parent' => $clone_to, 'menu_order' => $clone_from_post->menu_order, 'comment_status' => $clone_from_post->comment_status, 'ping_status' => $clone_from_post->ping_status, 'to_ping' => $clone_from_post->to_ping, ) ); if ( is_wp_error( $new_post_id ) ) { wp_send_json_error(); } // Copy post metadata. foreach ( $clone_post_meta as $key => $values ) { if ( 'positive' === $key || 'negative' === $key ) { continue; } foreach ( $values as $value ) { add_post_meta( $new_post_id, $key, $value ); } } $new_post = get_post( $new_post_id ); // add new subitems. $result[] = array( 'post' => $this->get_post_data( $new_post ), 'child' => $this->clone_child_docs( $clone_from_post->ID, $new_post_id ), ); endwhile; wp_reset_postdata(); return $result; } /** * Delete a doc * * @return void */ public function remove_doc() { check_ajax_referer( 'documentor-admin-nonce' ); $force_delete = false; $post_id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; if ( ! current_user_can( 'delete_post', $post_id ) ) { wp_send_json_error( __( 'You are not allowed to delete this item.', 'documentor' ) ); } if ( $post_id ) { // delete childrens first if found. $this->remove_child_docs( $post_id, $force_delete ); // delete main doc. wp_delete_post( $post_id, $force_delete ); } wp_send_json_success(); } /** * Remove child docs * * @param integer $parent_id - post id. * @param boolean $force_delete - force delete. */ public function remove_child_docs( $parent_id = 0, $force_delete ) { $childrens = get_children( array( 'post_parent' => $parent_id ) ); if ( $childrens ) { foreach ( $childrens as $child_post ) { // recursively delete. $this->remove_child_docs( $child_post->ID, $force_delete ); wp_delete_post( $child_post->ID, $force_delete ); } } } /** * Export as HTML * * @return void */ public function export_doc() { // phpcs:ignore $doc_id = isset( $_GET['doc_id'] ) ? absint( $_GET['doc_id'] ) : 0; if ( $doc_id ) { include_once dirname( __FILE__ ) . '/class-export.php'; $export_class = new Documentor_Export(); $export_class->run( $doc_id ); } exit; } /** * Get all docs * * @return void */ public function get_docs() { check_ajax_referer( 'documentor-admin-nonce' ); $docs = new WP_Query( array( 'post_type' => 'docs', 'post_status' => array( 'publish', 'draft', 'pending' ), 'posts_per_page' => -1, // phpcs:ignore 'orderby' => array( 'menu_order' => 'ASC', 'date' => 'DESC', ), ) ); $arranged = $this->build_tree( $docs->posts ); wp_send_json_success( $arranged ); } /** * Store feedback for an article * * @return void */ public function handle_feedback() { check_ajax_referer( 'documentor-ajax' ); $previous = array(); if ( isset( $_COOKIE['documentor_response'] ) ) { $cookies_data = explode( ',', sanitize_text_field( wp_unslash( $_COOKIE['documentor_response'] ) ) ); foreach ( $cookies_data as $data ) { $id = explode( '|', $data ); if ( isset( $id[0] ) ) { $previous[ (string) $id[0] ] = isset( $id[1] ) ? $id[1] : 'unknown'; } } } $post_id = isset( $_POST['post_id'] ) ? (string) sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) : 0; $type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : false; if ( $type && ! in_array( $type, array( 'positive', 'negative' ), true ) ) { $type = false; } // check previous response. if ( isset( $previous[ $post_id ] ) && ( 'unknown' === $previous[ $post_id ] || $type === $previous[ $post_id ] ) ) { $message = __( 'Sorry, you\'ve already recorded your feedback!', 'documentor' ); wp_send_json_error( $message ); } // seems new. if ( $type ) { $count = (int) get_post_meta( $post_id, $type, true ); update_post_meta( $post_id, $type, $count + 1 ); // remove previous feedback. if ( isset( $previous[ $post_id ] ) && 'unknown' !== $previous[ $post_id ] ) { $count = (int) get_post_meta( $post_id, $previous[ $post_id ], true ); update_post_meta( $post_id, $previous[ $post_id ], $count - 1 ); } $previous[ $post_id ] = $post_id . '|' . $type; $cookie_val = implode( ',', $previous ); setcookie( 'documentor_response', $cookie_val, time() + WEEK_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); } $message = __( 'Thank you for feedback!', 'documentor' ); wp_send_json_success( $message ); } /** * Prepare feedback suggestion to email. */ public function handle_feedback_suggestion() { check_ajax_referer( 'documentor-ajax' ); $email = documentor()->get_option( 'show_feedback_suggestion_email', 'documentor_single', '' ); if ( ! $email ) { $email = get_option( 'admin_email' ); } if ( ! $email ) { $response = __( 'Sorry, something went wrong on the server side!', 'documentor' ); wp_send_json_error( $response ); return; } $post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0; $post = $post_id ? get_post( $post_id ) : false; $feedback_type = isset( $_POST['feedback_type'] ) ? sanitize_text_field( wp_unslash( $_POST['feedback_type'] ) ) : ''; $suggestion = isset( $_POST['suggestion'] ) ? nl2br( htmlspecialchars( wp_unslash( $_POST['suggestion'] ) ) ) : ''; // phpcs:ignore $from = isset( $_POST['from'] ) && ! empty( $_POST['from'] ) ? sanitize_text_field( wp_unslash( $_POST['from'] ) ) : ''; if ( $post && $feedback_type && $suggestion ) { $is_sent = Documentor_Suggestion::send( array( 'post' => $post, 'from' => $from, 'feedback_type' => $feedback_type, 'suggestion' => $suggestion, ) ); if ( ! $is_sent ) { $response = __( 'Sorry, something went wrong with the mail server, your suggestions were not sent!', 'documentor' ); wp_send_json_error( $response ); return; } } $response = __( 'Thank you for suggestions!', 'documentor' ); wp_send_json_success( $response ); } /** * Sort docs * * @return void */ public function sort_docs() { check_ajax_referer( 'documentor-admin-nonce' ); $doc_ids = isset( $_POST['ids'] ) ? array_map( 'absint', $_POST['ids'] ) : array(); if ( $doc_ids ) { foreach ( $doc_ids as $order => $id ) { wp_update_post( array( 'ID' => $id, 'menu_order' => $order, ) ); } } exit; } /** * Build a tree of docs with parent-child relation * * @param array $docs - docs list. * @param integer $parent - post id. * * @return array */ public function build_tree( $docs, $parent = 0 ) { $result = array(); if ( ! $docs ) { return $result; } foreach ( $docs as $key => $doc ) { if ( (int) $doc->post_parent === (int) $parent ) { unset( $docs[ $key ] ); $cat_id = 0; $cat_name = ''; // get category. $terms = wp_get_post_terms( $doc->ID, 'docs_category' ); if ( ! empty( $terms ) && isset( $terms[0] ) ) { $cat_id = $terms[0]->term_id; $cat_name = $terms[0]->name; } // build tree and sort. $child = $this->build_tree( $docs, $doc->ID ); $result[] = array( 'post' => $this->get_post_data( $doc ), 'child' => $child, ); } } return $result; } /** * Sort callback for sorting posts with their menu order * * @param array $a - 1 post. * @param array $b - 2 post. * * @return int */ public function sort_callback( $a, $b ) { return $a['post']['order'] - $b['post']['order']; } public function ajax_template_part(){ check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce'); pagelayer_load_shortcodes(); $tags = ['pl_dm_feedback','pl_dm_article','pl_dm_breadcrumbs','pl_dm_adjacent_links','pl_dm_archive_box']; if(!in_array($_POST['template_name'], $tags)){ return false; } $content = get_comment_delimited_block_content( 'pagelayer/'.$_POST['template_name'], $_POST['data'] , ''); $wp['posts'] = pagelayer_the_content($content); pagelayer_json_output( $wp ); wp_die(); } public function ajax_template_import(){ check_ajax_referer('documentor_nonce', '_wpnonce'); include_once documentor()->plugin_path.'includes/template.php'; documentor_import_template_content( json_decode(documentor_get_conf(),true), documentor_get_content(),$_POST['atemplate']); wp_die(); } //Taking more time to load with do shortcode public function ajax_sidebar(){ check_ajax_referer('pagelayer_ajax', 'pagelayer_nonce'); $nav_list = wp_list_pages( array( 'title_li' => '', 'order' => 'menu_order', 'child_of' => !$_POST['data']['hide_parent'] ? 0 : documentor()->get_current_doc_id(), 'echo' => false, 'post_type' => 'docs', 'walker' => new Documentor_Walker_Docs(), ) ); if ( $nav_list ) { $html = ''; $html .= '
    '; $html .= $nav_list; $html .= '
'; } $wp['posts'] = $html; pagelayer_json_output( $wp ); wp_die(); } } new Documentor_Ajax(); PK!d"uushortcode_functions.phpnu[post_type != 'kkart_product'){ return; } // The default class $el['classes'][] = 'kkart-open-props'; $el['attr'][] = 'data-props-fields="'.$fname.'"'; $el['attr'][] = 'title="Open body props"'; }*/ // Price handler function pagelayer_sc_kkart_price(&$el){ global $post; $currency = get_kkart_currency_symbol(); if(pagelayer_is_live_template()){ $el['atts']['currency'] = $currency; $el['atts']['regular_price'] = 20; $el['atts']['sale_price'] = 10; $el['atts']['show_reg_price'] = true; $el['atts']['show_sale_price'] = true; return; } //TODO check price for variants product $product = kkart_get_product(); if(empty($product)){ return; } if($product->is_type('variable')){ if(pagelayer_is_live()){ $el['atts']['show_var_price'] = false; }else{ $regularPriceMin = kkart_price($product->get_variation_regular_price()); // Min regular price $salePriceMin = kkart_price($product->get_variation_sale_price()); // Min sale price $priceMin = kkart_price($product->get_variation_price()); // Min price // Max variation price $regularPriceMax = kkart_price($product->get_variation_regular_price('max')); // Max regular price $salePriceMax = kkart_price($product->get_variation_sale_price('max')); // Max sale price $priceMax = kkart_price($product->get_variation_price('max')); // Max price $el['atts']['show_var_price'] = $salePriceMin ? true : false; $el['atts']['reg_var_price_min'] = $salePriceMin; $el['atts']['reg_var_price_max'] = $regularPriceMax; if( $salePriceMin == $regularPriceMax ){ $el['atts']['reg_var_price_max'] = ''; } } } $regular_price = $product->get_regular_price(); $sale_price = $product->get_sale_price(); $show_reg_price = true; $show_sale_price = true; // This is for schedule if(!$product->is_on_sale()) { $show_reg_price = false; $sale_price = 0; } if(empty($regular_price)){ if(pagelayer_is_live()){ $regular_price = '0'; }else{ $show_sale_price = false; $show_reg_price = false; } } if(empty($sale_price)){ if(pagelayer_is_live()){ $sale_price = '0'; }else{ $sale_price = $regular_price; $regular_price = ''; $show_reg_price = false; } } $el['atts']['currency'] = $currency; $el['atts']['regular_price'] = $regular_price; $el['atts']['sale_price'] = $sale_price; $el['atts']['show_reg_price'] = $show_reg_price; $el['atts']['show_sale_price'] = $show_sale_price; } // Image gallery handler function pagelayer_sc_kkart_img_gallery(&$el){ global $product; $product = kkart_get_product(); $ids = array(); $urls = []; $all_urls = []; $links = []; $titles = []; $img = []; // Make the image URL $gallery_html = []; $primary_image = ''; $size = $el['atts']['size']; $inc = 0; if ( !empty( $product ) ) { $image_id = $product->get_image_id(); $attachment_ids = $product->get_gallery_image_ids(); $ids = array_merge([$image_id], $attachment_ids); } // If there is no gallery images if(empty($image_id)){ if(pagelayer_is_live() && !empty( $product )){ $urls = pagelayer_image(0); $primary_image = ''; }else{ $ids = array(0); } } if(pagelayer_is_live_template()){ // TO add five default images // Added dammy id's to set default images $ids = array(1.1,1.2,1.3,1.4,1.5); } foreach($ids as $k => $v){ $active_class = ""; $image = pagelayer_image($v); //pagelayer_print($image); if($inc == 0 && empty($primary_image)){ $active_class = "kkart-product-active"; $primary_image = ''.$image['alt'].''; } $final_urls[$v] = empty($image[$size.'-url']) ? @$image['url'] : $image[$size.'-url']; $urls['i'.$v] = @$image['url']; $links['i'.$v] = @$image['link']; $titles['i'.$v] = @$image['title']; foreach($image as $kk => $vv){ $si = strstr($kk, '-url', true); if(!empty($si)){ $all_urls['i'.$v][$si] = $vv; } } // If there is only one image then don't need to show gallary if(count($ids) > 1){ $gallery_html[] = ''; } $inc++; } //pagelayer_print($urls); //pagelayer_print($final_urls); //pagelayer_print($all_urls); if(pagelayer_is_live() && !empty($image_id)){ $image = pagelayer_image(0); $gallery_html[] = ''; } // Make the TMP vars if(!empty($urls)){ $el['tmp']['ids-urls'] = json_encode($urls); $el['tmp']['ids-all-urls'] = json_encode($all_urls); $el['tmp']['ids-all-links'] = json_encode($links); $el['tmp']['ids-all-titles'] = json_encode($titles); $el['atts']['gallery_html'] = implode('', $gallery_html); $el['atts']['primary_image'] = $primary_image; } $el['attr'][] = 'kkart-gallary-ids="'. implode(',', $ids) .'"'; } // Add to cart handler function pagelayer_sc_kkart_add_to_cart(&$el){ global $product; $product = kkart_get_product(); if(pagelayer_is_live()){ $el['atts']['kkart_cart_form'] = '
'; if(!empty($el['atts']['show_quantity'])){ $el['atts']['kkart_cart_form'] .= '
'; } $el['atts']['kkart_cart_form'] .= '
'; return; } if(!$product){ return; } ob_start(); do_action( 'kkart_' . $product->get_type() . '_add_to_cart', $el ); $form = ob_get_clean(); if ( ! $form ) { $el['atts']['kkart_cart_form'] = ''; return ''; } $el['atts']['kkart_cart_form'] = $form; } // Cart variable details handler function kkart_sc_cart_variable(&$el){ global $product, $cart_item_key, $cart_item; if(pagelayer_is_live()){ $el['atts']['variable_meta'] = '
color: Red
size: S
'; return; } //TODO check price for variants product $product = kkart_get_product(); if(empty($product) || !$product->is_type('variable') ){ $el['atts']['variable_meta'] = ''; return; } // Meta data. $el['atts']['variable_meta'] = kkart_get_formatted_cart_item_data( $cart_item, false, false ); // PHPCS: XSS ok. } // Cart items holder handler function kkart_sc_cart_items(&$el){ global $post, $cart_item_key, $cart_item; if(pagelayer_is_live()){ return; } $inner_content = ''; foreach ( KKART()->cart->get_cart() as $cart_item_key => $cart_item ) { if(empty($cart_item['product_id'])){ continue; } $id = (int) $cart_item['product_id']; $post = get_post( $id ); $product = apply_filters( 'kkart_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key ); if ( $product && $product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'kkart_cart_item_visible', true, $cart_item, $cart_item_key ) ) { $inner_content .= pagelayer_render_inner_content($el); } } wp_reset_query(); $el['inner_blocks'] = array(); $el['content'] = $inner_content; } // Cart items remove handler function kkart_sc_cart_item_remove(&$el){ global $post, $cart_item_key; if(empty($post)){ return; } // Delete items with refresh page //$el['atts']['item_remove_link'] = '?&kkart_remove_item='.@$current_cart_item; $el['atts']['cart_item_key'] = $cart_item_key; } //update the quantity of the cart function kkart_sc_cart_item_update(&$el){ global $post, $cart_item_key, $cart_item; $el['atts']['not_sold_individually'] = true; if ( !empty($cart_item['data']) && $cart_item['data']->is_sold_individually() ) { $el['atts']['not_sold_individually'] = false; } $el['atts']['kkart_cart_nonce'] = wp_create_nonce('kkart-cart'); $el['atts']['cart_item_key'] = $cart_item_key; } // Place order button function kkart_sc_place_order(&$el){ global $post,$cart_item_key; $el['atts']['process_checkout_nonce'] = wp_nonce_field('kkart-process_checkout', 'kkart-process-checkout-nonce', true, false); } // Cart item quantity handler function kkart_sc_cart_item_quantity(&$el){ global $cart_item, $post, $cart_item_key; if(pagelayer_is_live()){ $el['atts']['form_html'] = '
'; return; } $_product = $cart_item['data']; if ( $_product->is_sold_individually() ) { $min_quantity = 1; $max_quantity = 1; } else { $min_quantity = 0; $max_quantity = $_product->get_max_purchase_quantity(); } $el['atts']['form_html'] = kkart_quantity_input( array( 'input_name' => "cart[{$cart_item_key}][qty]", 'input_value' => $cart_item['quantity'], 'max_value' => $max_quantity, 'min_value' => $min_quantity, 'product_name' => $_product->get_name(), ), $_product, false ); } // Cart items price handler function kkart_sc_cart_price(&$el){ global $post; // TODO: Need to currecty all code $currency = get_kkart_currency_symbol(); if(pagelayer_is_live()){ $el['atts']['item_price'] = $currency.'20'; return; } if(empty($el['atts']['price_type']) ){ $el['atts']['item_price'] = 0; return; } $el['atts']['item_price'] = kkart_get_prices($el['atts']['price_type']); } // Get cart prices function kkart_get_prices(&$el){ global $cart_item, $post; $currency = get_kkart_currency_symbol(); if(pagelayer_is_live()){ return; } $cart_ob = KKART()->cart; if($el === 'grand_total'){ if( 'yes' === get_option( 'kkart_enable_shipping_calc' ) || 'yes' === get_option( 'kkart_shipping_cost_requires_address') ){ ob_start(); kkart_cart_totals_order_total_html(); $price = ob_get_clean(); }else{ $price = $cart_ob->get_cart_total() ; } return $price; } if($el === 'sub_total'){ $price = $cart_ob->get_cart_subtotal(); return $price; } if($el === 'all_items_total'){ $price = $cart_ob->get_total_ex_tax(); return $price; } if($el === 'discount'){ if( 'yes' == get_option( 'kkart_enable_coupons' ) ) { return kkart_coupon_price_html(); } } if($el ==='delivery_charges'){ $cart_ob->calculate_totals(); if( 'yes' === get_option( 'kkart_shipping_cost_requires_address') && is_cart() ){ $price = $currency.'0'; }elseif(is_checkout()){ $price = $cart_ob->get_cart_shipping_total(); }else{ $price = kkart_cart_totals_shipping_html(true); } return $price; } if($el === 'product_sub_total'){ $product = apply_filters( 'kkart_cart_item_product', $cart_item['data'], $cart_item ); if(empty($product)){ return ''; } $price = $cart_ob->get_product_subtotal($product, $cart_item['quantity'], $cart_item); return $price; } if($el === 'tax') { return kkart_tax_amount_html(); } } function kkart_sc_cart_prices(&$el){ if ( empty($el['atts']['hide_coupon'] ) && 'yes' === get_option( 'kkart_enable_coupons' ) ) { $el['atts']['show_coupon'] = true; } if( is_cart() ) { $el['atts']['checkout_proceed_link'] = esc_url(kkart_get_checkout_url()); } } function kkart_sc_checkout_form(&$el){ $tabs = array( 'login' => array( 'label' => (!empty($el['atts']['login_tab_text']) ? $el['atts']['login_tab_text'] : __('Login')), 'func' => 'kkart_checkout_login_form', ), 'billing' => array( 'label' => (!empty($el['atts']['login_tab_text']) ? $el['atts']['login_tab_text'] : __('Billing')), 'func' => 'kkart_checkout_billing', ), 'shipping' => array( 'label' => (!empty($el['atts']['login_tab_text']) ? $el['atts']['login_tab_text'] : __('Shipping')), 'func' => 'kkart_checkout_shipping', ), 'cart' => array( 'label' => (!empty($el['atts']['login_tab_text']) ? $el['atts']['login_tab_text'] : __('Cart')), 'func' => 'kkart_checkout_cart', ), 'payment' => array( 'label' => (!empty($el['atts']['login_tab_text']) ? $el['atts']['login_tab_text'] : __('Payment')), 'func' => 'kkart_checkout_payment', ) ); $div = ''; $edit_tab = empty($el['atts']['edit_button_title']) ? __('Change') : $el['atts']['edit_button_title']; $proceed = empty($el['atts']['proceed_button_title']) ? __('Proceed') : $el['atts']['proceed_button_title']; foreach($tabs as $key => $tab){ $div .= '
'.$tab['label'].'
'; if(is_callable($tab['func'])){ $div .= $tab['func']($el); } $div .= ''; if($key === 'login' && !is_user_logged_in() && ! KKART()->checkout()->is_registration_required()){ $div .= ''; } $div .= '
'; } $el['atts']['checkout_form'] = $div; } ///////////////////////////////////// // KKART Shortcode Functions ///////////////////////////////////// // Related products Handler - 2C function pagelayer_sc_kkart_product_related(&$el){ // start output buffer ob_start(); // If is related if($el['atts']['select_product'] == 'related'){ $args = [ 'posts_per_page' => 4, 'columns' => 4, 'orderby' => $el['atts']['orderby'], 'order' => $el['atts']['order'], ]; if ( ! empty( $el['atts']['posts_per_page'] ) ) { $args['posts_per_page'] = $el['atts']['posts_per_page']; } if ( ! empty( $el['atts']['columns'] ) ) { $args['columns'] = $el['atts']['columns']; } if(function_exists( 'kkart_related_products' )){ kkart_related_products($args); } // If is upsel; }elseif($el['atts']['select_product'] == 'upsell'){ $limit = '-1'; $columns = 4; $orderby = $el['atts']['orderby']; $order = $el['atts']['order']; if ( ! empty( $el['atts']['columns'] ) ) { $columns = $el['atts']['columns']; } if(function_exists( 'kkart_upsell_display' )){ kkart_upsell_display( $limit, $columns, $orderby, $order ); } } // Get data and clean output buffer $el['atts']['related_products'] = ob_get_clean(); } // WooCommers Pages - 2C function pagelayer_sc_kkart_pages(&$el){ // if is not empty if(!empty($el['atts']['pages'])){ $shortcode = '['. $el['atts']['pages'] .']'; $content = pagelayer_the_content($shortcode); // if is checkout page if ( 'kkart_checkout' === $el['atts']['pages'] && '
' == $content ) { $content = '
' . __( 'Your cart is currently empty.') . '
'; } } // If the content is empty if(empty($content)){ $content = '
' . __( 'Page content not found.') . '
'; } $el['atts']['page_content'] = $content; } // Product Pages - 2C function pagelayer_sc_kkart_product_categories(&$el){ $attributes = ''; $attributes .= ' number="'. $el['atts']['number'] .'" '; $attributes .= ' columns="'. $el['atts']['columns'] .'" '; $attributes .= ' hide_empty="'. (!empty($el['atts']['hide_empty']) ? 1 : 0) .'" '; $attributes .= ' orderby="'. $el['atts']['nuorderbymber'] .'" '; $attributes .= ' order="'. $el['atts']['order'] .'" '; if ( 'by_id' === $el['atts']['source'] ) { $attributes .= ' ids="'. $el['atts']['by_id'] .'" '; } elseif ( 'by_parent' === $el['atts']['source'] ) { $attributes .= ' parent="'. $el['atts']['parent'] .'" '; } elseif ( 'current_subcategories' === $el['atts']['source'] ) { $attributes .= ' parent="'. get_queried_object_id() .'" '; } $shortcode = '[product_categories '. $attributes .']'; // do_shortcode the shortcode $el['atts']['product_categories'] = pagelayer_the_content($shortcode); } // Products - 2C function pagelayer_sc_kkart_products(&$el){ global $product; if(pagelayer_is_live()){ return; } if( KKART()->session ){ kkart_print_notices(); } $atts = array(); $attributes = ''; $no_found = $el['atts']['no_found']; $type = $el['atts']['source']; // Hide the catalog order if( empty($el['atts']['allow_order']) ){ remove_action( 'kkart_before_shop_loop', 'kkart_catalog_ordering', 30 ); } // Hide the result count if( empty($el['atts']['show_result']) ){ remove_action( 'kkart_before_shop_loop', 'kkart_result_count', 20 ); } if( $type == 'pagelayer_current_query' ){ $atts['paginate'] = (!empty($el['atts']['paginate']) ? true : false); $atts['cache'] = false; // Set the current query add_action( 'kkart_shortcode_products_query', 'kkart_shortcode_current_query', 10, 10); // If product not found add_action( "kkart_shortcode_{$type}_loop_no_results", function ($attributes) use ($no_found){ echo '
'.$no_found.'
'; } ); $shortcode = new KKART_Shortcode_Products( $atts, $type, $el); $el['content'] = $shortcode->get_content(); $el['inner_blocks'] = array(); return true; } $atts['paginate'] = (!empty($el['atts']['paginate']) ? true : false); $atts['orderby'] = $el['atts']['orderby']; $atts['order'] = $el['atts']['order']; $atts['cache'] = false; $atts['limit'] = (!empty($el['atts']['limit']) ? $el['atts']['limit'] : 12); switch($type){ case 'recent_products': $atts = array_merge( array( 'orderby' => 'date', 'order' => 'DESC', 'category' => '', 'cat_operator' => 'IN', ), (array) $atts ); break; case 'sale_products': $atts = array_merge( array( 'orderby' => 'title', 'order' => 'ASC', 'category' => '', 'cat_operator' => 'IN', ), (array) $atts ); break; case 'best_selling_products': $atts = array_merge( array( 'category' => '', 'cat_operator' => 'IN', ), (array) $atts ); break; case 'top_rated_products': $atts = array_merge( array( 'orderby' => 'title', 'order' => 'ASC', 'category' => '', 'cat_operator' => 'IN', ), (array) $atts ); break; case 'featured_products': $atts = array_merge( array( 'orderby' => 'date', 'order' => 'DESC', 'category' => '', 'cat_operator' => 'IN', ), (array) $atts ); break; case 'upsell_product': $product = kkart_get_product(); $atts = (array) $atts; $atts['ids'] = ''; if(empty($product)){ break; } $atts['ids'] = implode(',', $product->get_upsell_ids()); break; case 'cross_sell_product': $atts = (array) $atts; $atts['ids'] = ''; $cross_sell_ids = KKART()->cart->get_cross_sells(); if(empty($cross_sell_ids)){ break; } $atts['ids'] = implode(',', $cross_sell_ids); break; case 'related_products': $atts = (array) $atts; $atts['ids'] = ''; $product = kkart_get_product(); if(empty($product)){ break; } $atts['ids'] = implode(',', kkart_get_related_products($product->get_id(), $atts['limit'], $product->get_upsell_ids())); break; case 'by_id': $atts = (array) $atts; $type = 'products'; $atts['ids'] = (!empty($el['atts']['ids']) ? $el['atts']['ids'] : ''); break; } if(isset($atts['ids']) && empty($atts['ids'])){ $content = ''; }else{ $shortcode = new KKART_Shortcode_Products( $atts, $type, $el ); $content = $shortcode->get_content(); } // If product not found if(empty($content)){ $el['atts']['product_title'] = ''; $content = '
'. __($no_found) .'
'; } $el['content'] = $content; $el['inner_blocks'] = array(); } // Archives Product Pages function pagelayer_sc_kkart_product_archives(&$el){ if(pagelayer_is_live()){ return; } if ( KKART()->session ) { kkart_print_notices(); } $atts['paginate'] = true; $atts['columns'] = isset($el['atts']['cols']) ? $el['atts']['cols'] : ''; $atts['limit'] = 10; $atts['cache'] = false; $no_found = $el['atts']['no_found']; if( empty($el['atts']['allow_order']) ){ remove_action( 'kkart_before_shop_loop', 'kkart_catalog_ordering', 30 ); } if( empty($el['atts']['show_result']) ){ remove_action( 'kkart_before_shop_loop', 'kkart_result_count', 20 ); } $type = 'pagelayer_current_query'; // We need to define costom if(pagelayer_is_live_template() || (wp_doing_ajax() && @$_REQUEST['action'] == 'pagelayer_product_archives')){ $type = ''; } // Set the current query add_action( 'kkart_shortcode_products_query', 'kkart_shortcode_current_query', 10, 10); // If product not found add_action( "kkart_shortcode_{$type}_loop_no_results", function ($attributes) use ($no_found){ echo '
'.$no_found.'
'; } ); $shortcode = new KKART_Shortcode_Products( $atts, $type, $el ); $el['content'] = $shortcode->get_content(); $el['inner_blocks'] = array(); } function kkart_fetch_variation_image($product, $option, $attribute_name){ $variations = $product->get_available_variations(); foreach($variations as $variation){ if(array_key_exists('attribute_'.$attribute_name, $variation['attributes']) && $variation['attributes']['attribute_'.$attribute_name] == $option){ return $variation['image']['thumb_src']; } } } function kkart_sc_product_variation(&$el){ global $post; $product = kkart_get_product($post->ID); $el['atts']['product_variation_html'] = ''; if($product->is_type('variable')){ if($el['atts']['selection_type'] === 'dropdown'){ $el['atts']['product_variation_html'] .= '
'; foreach($product->get_attributes() as $attribute_name => $options){ $attribute = (strpos($attribute_name,"pa_") !== false) ? explode("pa_",$attribute_name)[1]: $attribute_name; $el['atts']['product_variation_html'] .= ''; $el['atts']['product_variation_html'] .= ''; } } if($el['atts']['selection_type'] === 'checkbox'){ $el['atts']['product_variation_html'] .= '
'; foreach($product->get_attributes() as $attribute_name => $options){ $attribute = (strpos($attribute_name,"pa_") !==false) ? explode("pa_",$attribute_name)[1]: $attribute_name; $el['atts']['product_variation_html'] .= ''.ucfirst($attribute).''; $options['options'] = array_unique($options['options']); foreach($options['options'] as $option){ if($el['atts']['checkbox_options'] === 'text'){ if(taxonomy_exists($attribute_name)){ $term = get_term_by('id',$option,$attribute_name); $el['atts']['product_variation_html'] .= ''; continue; } $el['atts']['product_variation_html'] .= ''; }else if($el['atts']['checkbox_options'] === 'image'){ if(taxonomy_exists($attribute_name)){ $term = get_term_by('id',$option,$attribute_name); $image_url = kkart_fetch_variation_image($product,$term->name,$attribute_name); $el['atts']['product_variation_html'] .= ''; continue; } $image_url = kkart_fetch_variation_image($product,$option,$attribute_name); $el['atts']['product_variation_html'] .= ''; } } } $el['atts']['product_variation_html'] .= '
'; } } } // Archives Product item function pagelayer_sc_kkart_archive_item(&$el){ // Get permalinks $link = apply_filters( 'kkart_loop_product_link', get_the_permalink() ); $el['atts']['product_link'] = esc_url( $link ); } // Archives Product Thumbnail function pagelayer_sc_kkart_archive_thumb(&$el){ global $product; $product = kkart_get_product(); $urls = []; $all_urls = []; $ids = []; $size = isset($el['atts']['size']) ? $el['atts']['size'] : ''; $gallery = isset($el['atts']['gallery']) ? $el['atts']['gallery'] : ''; $thumb = ''; if ( !empty( $product ) ) { $image_id = $product->get_image_id(); if(!empty($gallery) && !empty($image_id)){ $attachment_ids = $product->get_gallery_image_ids(); $ids = array_merge([$image_id], $attachment_ids); }else{ $ids = $image_id; } } if(empty($ids)){ $image_id = get_option( 'kkart_placeholder_image', 0 ); $ids = $image_id; } if(empty($product) || pagelayer_is_live_template()){ if(!empty($gallery)){ $image_id = array(1,1,1,1,1); }else{ $image_id = 1; } $ids = $image_id; } if(is_array($ids)){ $thumb = ''; }else{ $image = pagelayer_image($ids); $thumb = ''; $urls = $image; foreach($image as $kk => $vv){ $si = strstr($kk, '-url', true); if(!empty($si)){ $all_urls[$si] = $vv; } } } //Make the TMP vars if(!empty($urls)){ $el['tmp']['ids-urls'] = json_encode($urls); $el['tmp']['ids-all-urls'] = json_encode($all_urls); $el['atts']['product_thumb'] = $thumb; if(in_array(@$el['atts']['controls'], ['arrows', 'none'])){ $el['attr'][] = ['.kkart-thumbnail-gallery' => 'data-pager="false"']; } if(in_array(@$el['atts']['controls'], ['pager', 'none'])){ $el['attr'][] = ['.kkart-thumbnail-gallery' => 'data-controls="false"']; } } // Get permalinks if(empty($el['atts']['unlink'])){ $link = apply_filters( 'kkart_product_link', get_the_permalink() ); $el['atts']['product_link'] = esc_url( $link ); } } // Product Title function pagelayer_sc_kkart_title(&$el){ global $post; if(pagelayer_is_live_template()){ $el['atts']['product_title'] = 'Product Title'; return; } // Get permalinks $link = apply_filters( 'kkart_product_link', get_the_permalink() ); $el['atts']['product_link'] = esc_url( $link ); $el['atts']['product_title'] = get_the_title(); } // Product Rating function pagelayer_sc_kkart_product_rating(&$el){ global $product; $product = kkart_get_product(); if(pagelayer_is_live_template()){ $el['atts']['product_rating'] = 2.5; $el['atts']['product_review_count'] = 1; return; } if(empty($product)){ $el['atts']['product_rating'] = 0; $el['atts']['product_review_count'] = 0; return; } $rating = $product->get_average_rating(); $count = $product->get_review_count(); // Added rating if ( kkart_review_ratings_enabled()) { $el['atts']['product_rating'] = $rating; $el['atts']['product_review_count'] = $count; } } // Product Rating function pagelayer_sc_kkart_sale(&$el){ global $product; if( pagelayer_is_live_template()){ $el['atts']['is_on_sale'] = true; if($el['atts']['show_discount']){ $el['atts']['sale_discount'] = '13%'; } return; } $product = kkart_get_product(); if( empty($product)){ return; } $el['atts']['is_on_sale'] = $product->is_on_sale(); if($el['atts']['show_discount'] && $el['atts']['is_on_sale']){ if($product->is_type('variable') || !$product->is_purchasable()){ $el['atts']['sale_text'] = __('Sale'); $el['atts']['sale_discount'] = ''; }else{ $regular_price = (int) $product->get_regular_price(); $sale_price = (int) $product->get_sale_price(); $discount_price = round((($regular_price - $sale_price) / $regular_price) * 100); $el['atts']['sale_discount'] = $discount_price.'%'; } } // Get permalinks $link = apply_filters( 'kkart_product_link', get_the_permalink() ); $el['atts']['product_link'] = esc_url( $link ); } // Product Rating function pagelayer_sc_kkart_archive_crt_btn(&$el){ global $product; $product = kkart_get_product(); $el['atts']['kkart_quantity_holder'] = ''; if(!$product || pagelayer_is_live_template()){ return; } $product_id = $product->get_id(); $args = array(); $defaults = array( 'quantity' => 1, 'class' => implode( ' ', array_filter( array( 'product_type_' . $product->get_type(), //$product->is_purchasable() && $product->is_in_stock() ? 'add_to_cart_button' : '', $product->supports( 'ajax_add_to_cart' ) && $product->is_purchasable() && $product->is_in_stock() ? 'ajax_add_to_cart' : '', ) ) ), 'attributes' => array( 'data-product_id' => $product_id, 'data-product_sku' => $product->get_sku(), 'aria-label' => $product->add_to_cart_description(), 'rel' => 'nofollow', ), ); $args = apply_filters( 'kkart_loop_add_to_cart_args', wp_parse_args( $args, $defaults ), $product ); $link = apply_filters( 'kkart_loop_product_link', get_the_permalink() ); $items = KKART()->cart->get_cart(); $cart_qty = 0; $cart_key = ''; foreach($items as $key => $item){ if($item['product_id'] != $product_id){ continue; } $cart_qty = $item['quantity']; $cart_key = $key; } if ( isset( $args['attributes']['aria-label'] ) ) { $args['attributes']['aria-label'] = wp_strip_all_tags( $args['attributes']['aria-label'] ); } //TODO check for variant products and out of stock $el['atts']['archive_crt_btn_link'] = ($product->supports( 'ajax_add_to_cart') ? $link : $product->add_to_cart_url()) ; $el['atts']['archive_crt_btn_qty'] = isset( $args['quantity'] ) ? $args['quantity'] : 1; $el['atts']['archive_crt_btn_class'] = isset( $args['class'] ) ? $args['class'] : ''; $el['atts']['archive_crt_btn_id'] = isset( $args['attributes']['data-product_id'] ) ? $args['attributes']['data-product_id'] : ''; $el['atts']['archive_crt_btn_sku'] = isset( $args['attributes']['data-product_sku'] ) ? $args['attributes']['data-product_sku'] : ''; $el['atts']['archive_crt_btn_label'] = isset( $args['attributes']['aria-label'] ) ? $args['attributes']['aria-label'] : ''; $el['atts']['archive_crt_btn_text'] = $product->is_purchasable() && $product->is_in_stock() ? __( $el['atts']['archive_crt_btn_text'], 'kkart' ) : __( 'Read more', 'kkart' ); if($product->is_type('variable') && $product->is_purchasable() && $product->is_in_stock()){ $el['atts']['archive_crt_btn_text'] = __( 'Select options', 'kkart' ); return; } if(!empty($cart_qty)){ $el['atts']['kkart_quantity_holder'] = '
'; $el['atts']['cart_item_key'] = $cart_key; $view_cart_text = (!empty($el['atts']['view_crt_btn_text'])) ? __($el['atts']['view_crt_btn_text']) : __('View cart', 'kkart'); $el['atts']['kkart_view_cart'] = ''.$view_cart_text.''; } } // Cart Item Count function pagelayer_sc_kkart_cart_item_count(&$el){ if(pagelayer_is_live()){ $el['atts']['item_count'] = 1; return; } // Total Items. $cart_html = KKART()->cart->get_cart(); $el['atts']['item_count'] = count($cart_html); } // Product meta render - 2C function pagelayer_sc_kkart_meta(&$el) { global $post; if (pagelayer_is_live_template()) { $el['atts']['sku_value'] = 'SKU1234'; $el['atts']['category_label'] = 'Category: '; $el['atts']['category_value'] = ''; $el['atts']['tag_label'] = 'Tag: '; $el['atts']['tag_value'] = ''; return; } $product = kkart_get_product(); if ( kkart_product_sku_enabled() && ( $product->get_sku() || $product->is_type( 'variable' ) ) ){ $el['atts']['sku_value'] = ( $sku = $product->get_sku() ) ? $sku : esc_html__( 'N/A', 'kkart' ); } if ( count( $product->get_category_ids() ) > 0 ){ $el['atts']['category_label'] = _n( 'Category:', 'Categories:', count( $product->get_category_ids() ), 'kkart' ) . ' '; $el['atts']['category_value'] = get_the_term_list( $product->get_id(), 'product_cat', '', ',', '' ); } if ( count( $product->get_tag_ids() ) > 0 ){ $el['atts']['tag_label'] = _n( 'Tag:', 'Tags:', count( $product->get_tag_ids() ), 'kkart' ) . ' '; $el['atts']['tag_value'] = get_the_term_list( $product->get_id(), 'product_tag', '', ',', '' ); } } //Product Short Description function pagelayer_sc_kkart_short_desc(&$el) { global $post; if(pagelayer_is_live_template()){ $el['atts']['product_short_desc'] = 'Demo Description'; return; } $el['atts']['product_short_desc'] = get_the_excerpt(); } // KKART breadcrumb render - 2C function kkart_sc_breadcrumb() { ob_start(); kkart_breadcrumb(); return ob_get_clean(); } // Get product categories - 2C function kkart_get_product_cat() { $categories = get_terms( 'product_cat' ); $options = []; foreach ( $categories as $category ) { $options[ $category->term_id ] = $category->name; } return $options; } // Get product categories - 2C function kkart_get_product_archives_desc() { ob_start(); do_action( 'kkart_archive_description' ); return ob_get_clean(); } // Get product additional Information - 2C function pagelayer_sc_kkart_addi_info(&$el) { global $product; $product = kkart_get_product(); if(pagelayer_is_live_template()){ $el['atts']['product_addi_info_heading'] = 'Additional Information'; $product_addi_info_html = ' label value'; $el['atts']['product_addi_info'] = $product_addi_info_html; return; } if($product->has_attributes()){ $heading = apply_filters( 'kkart_product_additional_information_heading', __( 'Additional information', 'kkart' ) ); $el['atts']['product_addi_info_heading'] = $heading; $product_attributes = $product->get_attributes(); //r_print($product_attributes); $product_attributes_html = ""; foreach ( $product_attributes as $product_attribute_key => $product_attribute ) : $product_attributes_html.= ' '.wp_kses_post( $product_attribute['name'] ).' '.wp_kses_post( $product_attribute['value'] ).' '; endforeach; $el['atts']['product_addi_info'] = $product_attributes_html; } } // Get product additional Information - 2C function kkart_get_product_data_tabs() { global $product, $post; $product = kkart_get_product(); if ( empty( $product ) ) { return __('Products not found'); } // We need load Pagelayer shortcodes pagelayer_load_shortcodes(); setup_postdata( $product->get_id()); ob_start(); kkart_output_product_data_tabs(); $data_tabs = ob_get_clean(); // If no data tabs if(empty($data_tabs)){ $data_tabs = __('Data tab not found'); } return $data_tabs; } // Get the HTML for menu cart function kkart_sc_menu_cart_html(){ // Maybe init cart $has_cart = is_a( KKART()->cart, 'KKART_Cart' ); if ( ! $has_cart ) { $session_class = apply_filters( 'kkart_session_handler', 'KKART_Session_Handler' ); KKART()->session = new $session_class(); KKART()->session->init(); KKART()->cart = new \KKART_Cart(); KKART()->customer = new \KKART_Customer( get_current_user_id(), true ); } // Get the cart values $widget_cart_is_hidden = apply_filters( 'kkart_widget_cart_is_hidden', is_cart() || is_checkout() ); $product_count = KKART()->cart->get_cart_contents_count(); $sub_total = KKART()->cart->get_cart_subtotal(); $cart_items = KKART()->cart->get_cart(); $toggle_button_link = $widget_cart_is_hidden ? kkart_get_cart_url() : '#'; /** workaround KKART Subscriptions issue that changes the behavior of is_cart() */ $toggle_button_classes = 'pagelayer-cart-button pagelayer-size-sm'; $toggle_button_classes .= $widget_cart_is_hidden ? ' pagelayer-menu-cart-hidden' : ''; $counter_attr = 'data-counter="' . $product_count . '"'; $cart_html = ''; // If is cart and checkout page the except this if ( ! $widget_cart_is_hidden ){ ob_start(); kkart_mini_cart(); $mini_cart_html = ob_get_clean(); $cart_html .= '
×
'. $mini_cart_html .'
'; } return $cart_html; } function pagelayer_sc_kkart_checkout_proceed_btn(&$el){ $el['atts']['checkout_proceed_link'] = esc_url(kkart_get_checkout_url()); } function pagelayer_sc_kkart_myaccount_tabs(&$el){ $tabs = array('dashboard' => 'Dashboard', 'downloads' => 'Downloads', 'orders' => 'Orders', 'edit-account' => 'Account Details', 'edit-address' => 'Addresses', 'support' => 'Support', 'customer-logout' => 'Logout'); $el['atts']['tab_holder'] = ''; $el['atts']['tab_content'] = ''; if(!is_user_logged_in()){ $register = get_option('kkart_enable_myaccount_registration'); $form = ''; $el['atts']['kkart_login_form'] = $form; }else{ foreach($tabs as $tk => $tv){ $current_user = wp_get_current_user(); if($tk == "customer-logout"){ $el['atts']['tab_holder'] .= ''.$tv.''; }else{ $el['atts']['tab_holder'] .= ''.$tv.''; $data_content .= '
'; switch($tk){ case 'dashboard': $data_content .= '

Hello '.$current_user->display_name.'( not '.$current_user->display_name.'? Logout)


'. __( 'From your account dashboard you can view your recent orders, manage your billing address, and edit your password and account details.', 'kkart' ) .'

'; break; case 'orders': $current_page = get_the_ID(); $order_col = array('order-number','order-date','order-status','order-total','order-actions'); $data_content .= '
'; $data_content .= kkart_account_orders($current_page, $order_col); $data_content .= '
'; break; case 'downloads': $download_col = array('download-product','download-file','download-remaining','download-expires'); $data_content .= '
'; $data_content .= kkart_account_downloads($download_col); $data_content .= '
'; break; case 'edit-account': $fields = array( 'account_first_name' => array( 'label' => __pl('First Name'), 'value' => (!empty($current_user) ? $current_user->first_name : '') ), 'account_last_name' => array( 'label' => __pl('Last Name'), 'value' => (!empty($current_user) ? $current_user->last_name : '') ), 'account_display_name' => array( 'label' => __pl('Display Name'), 'value' => (!empty($current_user) ? $current_user->display_name : '') ), 'account_email' => array( 'label' => __('Email-id'), 'value' => (!empty($current_user) ? $current_user->user_email : '') ), 'account_password' => array( 'password_current' => array( 'label' => __('Current Password') ), 'password_1' => array( 'label' => __('New Password') ), 'password_2' => array( 'label' => __('Confirm Password') ), ) ); if(!empty(kkart_get_notices('success'))){ $notice = kkart_get_notices('success'); $data_content .= '
'.$notice[0]['notice'].'
'; kkart_clear_notices(); } if(!empty(kkart_get_notices('error'))){ $notice = kkart_get_notices('error'); $data_content .= '
'.$notice[0]['notice'].'
'; kkart_clear_notices(); } $data_content .= ''; break; case 'support': $support_email = get_option('kkart_store_customer_care_email'); $support_email = empty($support_email) ? get_option( 'admin_email' ) : $support_email; $data_content .= __('You can contact us via email. Our email address is ').''.$support_email.''.__('. We will get back to you as soon as possible!'); break; case 'edit-address': $data_content .= '
'; $data_content .= kkart_checkout_billing($el); $data_content .= '
'; break; } $data_content .= '
'; } } $el['atts']['tab_content'] = $data_content; } } // Order received information handler function kkart_sc_order_info(&$el){ if(pagelayer_is_live()){ $el['oAtts']['editor_view'] = $el['atts']['editor_view'] = ''; $el['atts']['show_info'] = true; return; } $order = false; $order_id = @$_GET['order_id']; // Get the order. $order_id = apply_filters( 'kkart_thankyou_order_id', absint( $order_id ) ); $order_key = apply_filters( 'kkart_thankyou_order_key', empty( $_GET['key'] ) ? '' : kkart_clean( wp_unslash( $_GET['key'] ) ) ); // WPCS: input var ok, CSRF ok. if ( $order_id > 0 ) { $order = kkart_get_order( $order_id ); if ( ! $order || ! hash_equals( $order->get_order_key(), $order_key ) ) { $order = false; } } // Empty awaiting payment session. unset( KKART()->session->order_awaiting_payment ); // In case order is created from admin, but paid by the actual customer, store the ip address of the payer // when they visit the payment confirmation page. if ( $order && $order->is_created_via( 'admin' ) ) { $order->set_customer_ip_address( KKART_Geolocation::get_ip_address() ); $order->save(); } // Empty current cart. kkart_empty_cart(); $div = ''; if( $order ){ if( $order->has_status( 'failed' )){ $el['atts']['show_failed'] = true; $el['atts']['failed_text'] .= '

'. esc_html( 'Pay', 'kkart' ).''; if( is_user_logged_in() ){ $el['atts']['failed_text'] .= ''. esc_html( 'My account', 'kkart' ) .''; } $el['atts']['failed_text'] .= '

'; }else{ $vars = array( '$order_number' => $order->get_order_number(), '$order_date' => kkart_format_datetime( $order->get_date_created() ), '$billing_email' => ( is_user_logged_in() && $order->get_user_id() === get_current_user_id() && $order->get_billing_email() ) ? $order->get_billing_email() : '', '$order_total' => $order->get_formatted_order_total(), '$payment_method' => ($order->get_payment_method_title() ? wp_kses_post( $order->get_payment_method_title() ) : '') ); $el['atts']['show_info'] = true; // Create the HTML object $node = pagelayerQuery::parseStr($el['atts']['info_text']); foreach($vars as $key => $value){ if(empty($value)){ foreach($node('[if="'.$key.'"]') as $v){ $v->remove(); } } } $el['atts']['info_text'] = $node->html(); foreach($vars as $key => $value){ $el['atts']['info_text'] = str_replace($key, $value, $el['atts']['info_text']); } } }else{ $el['atts']['show_not_found'] = true; $el['atts']['order_not_found_txt'] = '

'. apply_filters( 'kkart_thankyou_order_not_found_text', $el['atts']['order_not_found_txt'], null ) .'

'; } } // Order received details handler function kkart_sc_order_details(&$el){ if(pagelayer_is_live()){ $el['atts']['order_details'] = 'Order detail Holder'; return; } $order_id = @$_GET['order_id']; // Get the order. $order_id = apply_filters( 'kkart_thankyou_order_id', absint( $order_id ) ); $order = kkart_get_order( $order_id ); if ( ! $order ) { $el['atts']['order_details'] = 'Order Not Found'; return; } $order_items = $order->get_items( apply_filters( 'kkart_purchase_order_item_types', 'line_item' ) ); $show_purchase_note = $order->has_status( apply_filters( 'kkart_purchase_note_order_statuses', array( 'completed', 'processing' ) ) ); $show_customer_details = is_user_logged_in() && $order->get_user_id() === get_current_user_id(); $downloads = $order->get_downloadable_items(); $show_downloads = $order->has_downloadable_item() && $order->is_download_permitted(); if ( $show_downloads ) { $el['atts']['show_downloads'] = true; ob_start(); echo ''; foreach( kkart_get_account_downloads_columns() as $column_id => $column_name ){ echo ''; } echo ''; foreach( $downloads as $download ){ echo ''; foreach(kkart_get_account_downloads_columns() as $column_id => $column_name ){ echo ''; } echo ''; } echo '
'. esc_html( $column_name ) .'
'; if ( has_action( 'kkart_account_downloads_column_' . $column_id ) ) { do_action( 'kkart_account_downloads_column_' . $column_id, $download ); } else { switch ( $column_id ) { case 'download-product': if ( $download['product_url'] ) { echo '' . esc_html( $download['product_name'] ) . ''; } else { echo esc_html( $download['product_name'] ); } break; case 'download-file': echo '' . esc_html( $download['download_name'] ) . ''; break; case 'download-remaining': echo is_numeric( $download['downloads_remaining'] ) ? esc_html( $download['downloads_remaining'] ) : esc_html__( '∞', 'kkart' ); break; case 'download-expires': if ( ! empty( $download['access_expires'] ) ) { echo ''; } else { esc_html_e( 'Never', 'kkart' ); } break; } } echo '
'; $el['atts']['download_details'] = ob_get_clean(); } $order_details = ''; ob_start(); do_action( 'kkart_order_details_before_order_table_items', $order ); foreach ( $order_items as $item_id => $item ) { $product = $item->get_product(); $purchase_note = $product ? $product->get_purchase_note() : ''; if ( ! apply_filters( 'kkart_order_item_visible', true, $item ) ) { continue; } echo ''; if( $show_purchase_note && $purchase_note ){ echo ''; } } do_action( 'kkart_order_details_after_order_table_items', $order ); $order_details .= ob_get_clean() .''; foreach ( $order->get_order_item_totals() as $key => $total ) { $order_details .= ''; } if($order->get_customer_note()){ $order_details .= ''; } $order_details .= '
'. esc_html( 'Product', 'kkart' ) .' '. esc_html( 'Total', 'kkart' ) .'
'; $is_visible = $product && $product->is_visible(); $product_permalink = apply_filters( 'kkart_order_item_permalink', $is_visible ? $product->get_permalink( $item ) : '', $item, $order ); echo apply_filters( 'kkart_order_item_name', $product_permalink ? sprintf( '%s', $product_permalink, $item->get_name() ) : $item->get_name(), $item, $is_visible ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $qty = $item->get_quantity(); $refunded_qty = $order->get_qty_refunded_for_item( $item_id ); if ( $refunded_qty ) { $qty_display = '' . esc_html( $qty ) . ' ' . esc_html( $qty - ( $refunded_qty * -1 ) ) . ''; } else { $qty_display = esc_html( $qty ); } echo apply_filters( 'kkart_order_item_quantity_html', ' ' . sprintf( '× %s', $qty_display ) . '', $item ); do_action( 'kkart_order_item_meta_start', $item_id, $item, $order, false ); kkart_display_item_meta( $item ); do_action( 'kkart_order_item_meta_end', $item_id, $item, $order, false ); echo ' '. $order->get_formatted_line_subtotal( $item ) .'
'. wpautop( do_shortcode( wp_kses_post( $purchase_note ) ) ) .'
'. esc_html( $total['label'] ) .' '. (( 'payment_method' === $key ) ? esc_html( $total['value'] ) : wp_kses_post( $total['value'] )) .'
'. esc_html( 'Note:', 'kkart' ) .' '. wp_kses_post( nl2br( wptexturize( $order->get_customer_note() ) ) ) .'
'; $el['atts']['order_details'] = $order_details; } // TODO improve this for live editor and parse with variables // Order received customer handler function kkart_sc_order_address(&$el){ if(pagelayer_is_live()){ $el['atts']['billing_details'] = 'Billing Address holder'; return; } $order_id = @$_GET['order_id']; // Get the order. $order_id = apply_filters( 'kkart_thankyou_order_id', absint( $order_id ) ); $order = kkart_get_order( $order_id ); if ( ! $order ) { return; } $show_shipping = (! kkart_ship_to_billing_address_only() && $order->needs_shipping_address()); $billing_details = '
'. wp_kses_post( $order->get_formatted_billing_address( esc_html__( 'N/A', 'kkart' ) ) ); if($order->get_billing_phone()){ $billing_details .= '

'. esc_html( $order->get_billing_phone() ) .'

'; } if( $order->get_billing_email()){ $billing_details .= ''; } $billing_details .= '
'; $el['atts']['billing_details'] = $billing_details; if( $show_shipping ){ $shipping_details = '
'. wp_kses_post( $order->get_formatted_shipping_address( esc_html__( 'N/A', 'kkart' ) ) ) .'
'; $el['atts']['show_shipping'] = true; $el['atts']['shipping_details'] = $shipping_details; } } // Order pay handler function kkart_sc_order_pay(&$el){ if(pagelayer_is_live()){ $el['atts']['show_pay_form'] = true; $el['atts']['order_pay_form'] = 'Pay Form Holder'; return; } $order_id = absint( @$_GET['order_id'] ); $div = ''; // Pay for existing order. if ( isset( $_GET['pay_for_order'], $_GET['key'] ) && $order_id ) { // WPCS: input var ok, CSRF ok. try { $order_key = isset( $_GET['key'] ) ? kkart_clean( wp_unslash( $_GET['key'] ) ) : ''; // WPCS: input var ok, CSRF ok. $order = kkart_get_order( $order_id ); // Order or payment link is invalid. if ( ! $order || $order->get_id() !== $order_id || ! hash_equals( $order->get_order_key(), $order_key ) ) { throw new Exception( __( 'Sorry, this order is invalid and cannot be paid for.', 'kkart' ) ); } // Logged out customer does not have permission to pay for this order. if ( ! current_user_can( 'pay_for_order', $order_id ) && ! is_user_logged_in() ) { $el['atts']['show_login'] = true; $el['atts']['order_pay_login'] = '
' . esc_html__( 'Please log in to your account below to continue to the payment form.', 'kkart' ) . '
'. kkart_login_form( array( 'redirect' => $order->get_checkout_payment_url(), ), false ); $el['atts']['messages'] = $div; return; } // Add notice if logged in customer is trying to pay for guest order. if ( ! $order->get_user_id() && is_user_logged_in() ) { // If order has does not have same billing email then current logged in user then show warning. if ( $order->get_billing_email() !== wp_get_current_user()->user_email ) { ob_start(); kkart_print_notice( __( 'You are paying for a guest order. Please continue with payment only if you recognize this order.', 'kkart' ), 'error' ); $div .= ob_get_clean(); } } // Logged in customer trying to pay for someone else's order. if ( ! current_user_can( 'pay_for_order', $order_id ) ) { throw new Exception( __( 'This order cannot be paid for. Please contact us if you need assistance.', 'kkart' ) ); } // Does not need payment. if ( ! $order->needs_payment() ) { /* translators: %s: order status */ throw new Exception( sprintf( __( 'This order’s status is “%s”—it cannot be paid for. Please contact us if you need assistance.', 'kkart' ), kkart_get_order_status_name( $order->get_status() ) ) ); } // Ensure order items are still stocked if paying for a failed order. Pending orders do not need this check because stock is held. if ( ! $order->has_status( kkart_get_is_pending_statuses() ) ) { $quantities = array(); foreach ( $order->get_items() as $item_key => $item ) { if ( $item && is_callable( array( $item, 'get_product' ) ) ) { $product = $item->get_product(); if ( ! $product ) { continue; } $quantities[ $product->get_stock_managed_by_id() ] = isset( $quantities[ $product->get_stock_managed_by_id() ] ) ? $quantities[ $product->get_stock_managed_by_id() ] + $item->get_quantity() : $item->get_quantity(); } } foreach ( $order->get_items() as $item_key => $item ) { if ( $item && is_callable( array( $item, 'get_product' ) ) ) { $product = $item->get_product(); if ( ! $product ) { continue; } if ( ! apply_filters( 'kkart_pay_order_product_in_stock', $product->is_in_stock(), $product, $order ) ) { /* translators: %s: product name */ throw new Exception( sprintf( __( 'Sorry, "%s" is no longer in stock so this order cannot be paid for. We apologize for any inconvenience caused.', 'kkart' ), $product->get_name() ) ); } // We only need to check products managing stock, with a limited stock qty. if ( ! $product->managing_stock() || $product->backorders_allowed() ) { continue; } // Check stock based on all items in the cart and consider any held stock within pending orders. $held_stock = kkart_get_held_stock_quantity( $product, $order->get_id() ); $required_stock = $quantities[ $product->get_stock_managed_by_id() ]; if ( ! apply_filters( 'kkart_pay_order_product_has_enough_stock', ( $product->get_stock_quantity() >= ( $held_stock + $required_stock ) ), $product, $order ) ) { /* translators: 1: product name 2: quantity in stock */ throw new Exception( sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order (%2$s available). We apologize for any inconvenience caused.', 'kkart' ), $product->get_name(), kkart_format_stock_quantity_for_display( $product->get_stock_quantity() - $held_stock, $product ) ) ); } } } } KKART()->customer->set_props( array( 'billing_country' => $order->get_billing_country() ? $order->get_billing_country() : null, 'billing_state' => $order->get_billing_state() ? $order->get_billing_state() : null, 'billing_postcode' => $order->get_billing_postcode() ? $order->get_billing_postcode() : null, ) ); KKART()->customer->save(); $available_gateways = KKART()->payment_gateways->get_available_payment_gateways(); $order_button_text = apply_filters( 'kkart_pay_order_button_text', __( 'Pay for order', 'kkart' ) ); $totals = $order->get_order_item_totals(); if ( count( $available_gateways ) ) { current( $available_gateways )->set_current(); } $el['atts']['show_pay_form'] = true; $el['atts']['order_pay_form'] = '
'; ob_start(); if(count( $order->get_items() ) > 0){ foreach( $order->get_items() as $item_id => $item ){ if ( ! apply_filters( 'kkart_order_item_visible', true, $item ) ) { continue; } echo ''; } } $el['atts']['order_pay_form'] .= ob_get_clean() .' '; if($totals){ foreach($totals as $total){ $el['atts']['order_pay_form'] .= ''; } } $el['atts']['order_pay_form'] .= '
'. esc_html( 'Product', 'kkart' ) .' '. esc_html( 'Qty', 'kkart' ) .' '. esc_html( 'Totals', 'kkart' ) .'
'. apply_filters( 'kkart_order_item_name', esc_html( $item->get_name() ), $item, false ); do_action( 'kkart_order_item_meta_start', $item_id, $item, $order, false ); kkart_display_item_meta( $item ); do_action( 'kkart_order_item_meta_end', $item_id, $item, $order, false ); echo ' '. apply_filters( 'kkart_order_item_quantity_html', ' ' . sprintf( '× %s', esc_html( $item->get_quantity() ) ) . '', $item ) .' '. $order->get_formatted_line_subtotal( $item ) .'
'. $total['label'] .' '. $total['value'] .'
'; ob_start(); if($order->needs_payment()){ echo '
    '; if ( ! empty( $available_gateways ) ) { foreach ( $available_gateways as $gateway ) { echo '
  • chosen, true, false ).' data-order_button_text="'. esc_attr( $gateway->order_button_text ).'" /> '; if( $gateway->has_fields() || $gateway->get_description() ){ echo '
    chosen ) ? 'style="display:none;"' : '') .' >'; $gateway->payment_fields(); echo '
    '; } echo '
  • '; } } else { echo '
  • ' . apply_filters( 'kkart_no_available_payment_methods_message', esc_html__( 'Sorry, it seems that there are no available payment methods for your location. Please contact us if you require assistance or wish to make alternate arrangements.', 'kkart' ) ) . '
  • '; // @codingStandardsIgnoreLine } echo '
'; } echo '
'; kkart_checkout_terms(); do_action( 'kkart_pay_order_before_submit' ); echo apply_filters( 'kkart_pay_order_button_html', '' ); do_action( 'kkart_pay_order_after_submit' ); wp_nonce_field( 'kkart-pay', 'kkart-pay-nonce' ); $el['atts']['order_pay_form'] .= ob_get_clean() .'
'; } catch ( Exception $e ) { ob_start(); kkart_print_notice( $e->getMessage(), 'error' ); $div .= ob_get_clean(); } } elseif ( $order_id ) { // Pay for order after checkout step. $order_key = isset( $_GET['key'] ) ? kkart_clean( wp_unslash( $_GET['key'] ) ) : ''; // WPCS: input var ok, CSRF ok. $order = kkart_get_order( $order_id ); if ( $order && $order->get_id() === $order_id && hash_equals( $order->get_order_key(), $order_key ) ) { if ( $order->needs_payment() ) { // To load payment geteways $available_gateways = KKART()->payment_gateways->get_available_payment_gateways(); $el['atts']['show_details'] = true; $el['atts']['order_pay_details'] = '
  • '. esc_html( 'Order number:', 'kkart' ) .' '. esc_html( $order->get_order_number() ) .'
  • '. esc_html( 'Date:', 'kkart' ) .' '. esc_html( kkart_format_datetime( $order->get_date_created() ) ) .'
  • '. esc_html( 'Total:', 'kkart' ).' '. wp_kses_post( $order->get_formatted_order_total() ).'
  • '; if($order->get_payment_method_title()){ $el['atts']['order_pay_details'] .= '
  • '. esc_html( 'Payment method:', 'kkart' ) .' '. wp_kses_post( $order->get_payment_method_title() ) .'
  • '; } $el['atts']['order_pay_details'] .= '
'; ob_start(); do_action( 'kkart_receipt_' . $order->get_payment_method(), $order->get_id() ); $el['atts']['order_pay_details'] .= ob_get_clean(); } else { ob_start(); /* translators: %s: order status */ kkart_print_notice( sprintf( __( 'This order’s status is “%s”—it cannot be paid for. Please contact us if you need assistance.', 'kkart' ), kkart_get_order_status_name( $order->get_status() ) ), 'error' ); $div .= ob_get_clean(); } } else { ob_start(); kkart_print_notice( __( 'Sorry, this order is invalid and cannot be paid for.', 'kkart' ), 'error' ); $div .= ob_get_clean(); } } else { ob_start(); kkart_print_notice( __( 'Invalid order.', 'kkart' ), 'error' ); $div .= ob_get_clean(); } $el['atts']['messages'] = $div; } // Buy now handler function kkart_sc_buy_now(&$el){ $_product = kkart_get_product( get_the_ID() ); $el['atts']['buy_now_show'] = true; if(pagelayer_is_live() || empty($_product)){ return; } if ( !$_product->is_type( 'simple' ) || !$_product->is_purchasable() || !$_product->is_in_stock() ) { $el['atts']['buy_now_show'] = false; return; } $el['atts']['buy_now_url'] = esc_url( add_query_arg( array( 'add-to-cart' => get_the_ID(), 'buy-now' => get_the_ID(), ), kkart_get_cart_url() ) ); }PK!7class-template-loader.phpnu[get_option( 'docs_page_id', 'documentor_settings', false ); add_filter( 'template_include', array( __CLASS__, 'template_loader' ) ); // To make the links like /docs/space/category/arctile-name to /docs/space/arctile-name add_filter('post_type_link', array( __CLASS__, 'permalink' ), 10001, 4); } /** * Load a template. * * Handles template usage so that we can use our own templates instead of the themes. * * Templates are in the 'templates' folder. documentor looks for theme. * overrides in /theme/documentor/ by default. * * @param string $template - template name. * @return string */ public static function template_loader( $template ) { if ( is_embed() ) { return $template; } $default_file = self::get_template_loader_default_file(); if ( $default_file ) { /** * Filter hook to choose which files to find before Documentor does it's own logic. * * @var array */ $search_files = self::get_template_loader_files( $default_file ); $template = locate_template( $search_files ); if ( ! $template ) { $template = documentor()->template_path . $default_file; } } return $template; } /** * Get the default filename for a template. * * @return string */ private static function get_template_loader_default_file() { $default_file = ''; if ( is_singular( 'docs' ) ) { $default_file = 'single.php'; documentor()->is_single = true; } elseif ( is_post_type_archive( 'docs' ) || self::$docs_archive_id && is_page( self::$docs_archive_id ) ) { $default_file = 'archive.php'; documentor()->is_archive = true; // Add query for page docs. global $wp_query; $args = array( 'post_type' => 'docs', 'posts_per_page' => -1, // phpcs:ignore 'post_parent' => 0, 'orderby' => array( 'menu_order' => 'ASC', 'date' => 'DESC', ), ); // prepare args for search page. if ( ! is_admin() && is_search() ) { $default_file = 'search.php'; unset( $args['posts_per_page'] ); unset( $args['post_parent'] ); $args['s'] = get_search_query(); // phpcs:ignore $parent = isset( $_GET['child_of'] ) ? sanitize_text_field( wp_unslash( $_GET['child_of'] ) ) : false; $parent = intval( $parent ); // we need to get all docs IDs and the use it in WP_Query as we need get also all childrens. if ( $parent ) { $post__in = array( $parent => $parent ); $children_docs = get_pages( array( 'child_of' => $parent, 'post_type' => 'docs', 'depth' => -1, ) ); if ( $children_docs ) { $post__in = array_merge( $post__in, wp_list_pluck( $children_docs, 'ID' ) ); } $args['post__in'] = $post__in; } } // make order by term. if ( 'archive.php' === $default_file ) { $categories = get_terms( array( 'taxonomy' => 'docs_category', 'hide_empty' => false, ) ); // we need to make query and loop over items and sort it by term. if ( ! empty( $categories ) ) { $docs_by_cat = array( 0 => array(), ); // get all available terms in array. foreach ( $categories as $cat ) { $docs_by_cat[ $cat->slug ] = array(); } // get parent docs. $parent_docs = get_pages( array( 'post_type' => 'docs', 'parent' => 0, 'sort_column' => 'menu_order', ) ); if ( $parent_docs ) { // set all doc IDs to array by terms. foreach ( $parent_docs as $doc ) { $term = get_the_terms( $doc, 'docs_category' ); if ( $term && ! empty( $term ) ) { $term = $term[0]->slug; } else { $term = 0; } $docs_by_cat[ $term ][] = $doc->ID; } // add posts IDs in post__in. if ( count( $docs_by_cat ) >= 2 ) { $args['post__in'] = array(); foreach ( $docs_by_cat as $docs ) { $args['post__in'] = array_merge( $args['post__in'], $docs ); } $args['orderby'] = 'post__in'; } } } } $wp_query = new WP_Query( $args ); // phpcs:ignore } return $default_file; } /** * Get an array of filenames to search for a given template. * * @param string $default_file The default file name. * @return string[] */ private static function get_template_loader_files( $default_file ) { $search_files = apply_filters( 'documentor_template_loader_files', array(), $default_file ); if ( is_page_template() ) { $search_files[] = get_page_template_slug(); } $search_files[] = '/documentor/' . $default_file; return array_unique( $search_files ); } // Change the post permalink public static function permalink($post_link, $post, $leavename, $sample){ // Only for docs type if($post->post_type == documentor()->post_type){ //die(home_url('/docs').' - '.$post_link); $url = get_permalink( self::$docs_archive_id ); // We need to clean extra parts in the docs $section = str_replace($url, '', $post_link); $section = str_replace(home_url(), '', $section); //in case the url dosent have custom post type $section = explode('/', trim($section, '/')); $count = count($section); //This is to reduce the URL length. if($count > 2) { for($i = 1; $i < ($count - 1); $i++){ unset($section[$i]); } } $post_link = $url.implode('/', $section); //die($post_link); } return $post_link; } } Documentor_Template_Loader::init(); PK!9&&shortcodes.phpnu[ __('Product Price'), 'group' => 'kkart', 'use_inside' => ['pl_kkart_archive_item'], 'edit_props' => ['.kkart-regular-price' => '_regular_price', '.kkart-sale-price' => '_sale_price'], 'html' => '
{{currency}}{{regular_price}} {{currency}}{{sale_price}} {{reg_var_price_min}} - {{reg_var_price_max}}
', 'params' => array( 'prices' => array( 'type' => 'radio', 'label' => __('Price'), 'default' => 'regular', 'list' => [ 'regular' => __('Regular Price'), 'sale' => __('Sale Price'), ], ), 'rp_color' => array( 'type' => 'color', 'label' => __('Color'), 'show' => ['prices' => 'regular'], 'css' => ['{{element}} .kkart-price-holder del' => 'color:{{val}}'], ), 'rp_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'show' => ['prices' => 'regular'], 'css' => [ '{{element}} .kkart-price-holder del' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), 'sp_color' => array( 'type' => 'color', 'label' => __('Color'), 'show' => ['prices' => 'sale'], 'css' => ['{{element}} .kkart-sale-price-cnt' => 'color:{{val}}'], ), 'sp_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'show' => ['prices' => 'sale'], 'css' => [ '{{element}} .kkart-sale-price-cnt' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), 'p_position' => array( 'type' => 'checkbox', 'label' => __('Flip regular price'), 'addClass' => ['{{element}} .kkart-price-holder' => 'kkart-price-flip'], ), 'space' => array( 'type' => 'spinner', 'label' => __('Space'), 'css' => ['{{element}} .kkart-price-amount' => 'margin-right:{{val}}px;'] ), ), ) ); // Image gallery pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_img_gallery', array( 'name' => __('Product gallery'), 'group' => 'kkart', 'html' => '', 'params' => array( 'hide_gallery' => array( 'type' => 'checkbox', 'label' => __('Hide Gallery'), 'css' => ['{{element}} .kkart-product-gallery-container' => 'display: none'] ), 'size' => array( 'type' => 'select', 'label' => 'Gallery Image Size', 'default' => 'thumbnail', 'list' => array( 'full' => __('Full'), 'large' => __('Large'), 'medium' => __('Medium'), 'thumbnail' => __('Thumbnail'), 'custom' => __('Custom'), ), ), 'gcustom_size' => array( 'type' => 'dimension', 'label' => 'Gallery Image Custom Size', 'units' => ['px', 'em', '%'], 'screen' => 1, 'css' => ['{{element}} .kkart-gallery-item img' => 'width: {{val[0]}}; height: {{val[1]}};'], 'req' => array( 'size' => 'custom' ), ), 'galign' => array( 'type' => 'radio', 'label' => 'Gallery Image Alignment', 'default' => 'left', 'addAttr' => 'align="{{align}}"', 'css' => ['{{element}} .kkart-product-gallery-container' => 'text-align: {{val}}', '{{element}} .kkart-product-gallery-container .kkart-product-gallery-ul' => 'text-align: {{val}}'], 'list' => array( 'left' => __('Start'), 'center' => __('Center'), 'right' => __('End'), ) ), 'gposition' => array( 'label' => 'Gallery Container Position', 'type' => 'radio', 'default' => 'bottom', 'list' => array( 'left' => __('Left'), 'top' => __('Top'), 'right' => __('Right'), 'bottom' => __('Bottom') ) ), 'gcolumns' => array( 'type' => 'spinner', 'label' => __('Gallery Image Count'), 'default' => 5, 'addAttr' => ['{{element}} .kkart-product-gallery-ul' => 'data-slides-count={{gcolumns}}'], ), 'gholder_size' => array( 'type' => 'dimension', 'label' => 'Gallery Holder Size', 'units' => ['px', 'em', '%'], 'screen' => 1, 'css' => ['{{element}} .kkart-product-gallery-ul' => 'width: {{val[0]}}; height: {{val[1]}};'], ), 'hover_slider' => array( 'type' => 'checkbox', 'label' => __('Hover Slider'), 'default' => '', 'addAttr' => ['{{element}} .kkart-product-gallery-ul' => 'data-slides-hover={{hover_slider}}'], ), ), 'gimg_border_style' => array( 'gimg_bor_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', //'no_val' => 1,// Dont set any value to element 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'gimg_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-product-active' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'gimg_bor_hover' => '' ), ), 'gimg_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-product-active' => 'border-color: {{val}};'], 'req' => array( '!gimg_border_type' => '' ), 'show' => array( 'gimg_bor_hover' => '' ), ), 'gimg_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-active' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => [ '!gimg_border_type' => '' ], 'show' => array( 'gimg_bor_hover' => '' ), ), 'gimg_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-active' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!gimg_border_type' => '', ), 'show' => array( 'gimg_bor_hover' => '', ), ), 'gimg_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-product-gimage:hover' => 'border-style: {{val}}' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'gimg_bor_hover' => 'hover' ), ), 'gimg_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color Hover'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-product-gimage:hover' => 'border-color: {{val}};'], 'req' => array( '!gimg_border_type_hover' => '' ), 'show' => array( 'gimg_bor_hover' => 'hover' ), ), 'gimg_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width Hover'), 'screen' => 1, 'css' => [ '{{element}} .kkart-product-gimage:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px;' ], 'req' => [ '!gimg_border_type_hover' => '' ], 'show' => array( 'gimg_bor_hover' => 'hover' ), ), 'gimg_border_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius Hover'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-gimage:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!gimg_border_type_hover' => '', ), 'show' => array( 'gimg_bor_hover' => 'hover', ), ), ), 'primary_image' => array( 'palign' => array( 'label' => 'Primary Image Alignment', 'type' => 'radio', 'default' => 'center', 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right') ) ), 'pspace' => array( 'label' => 'Margin', 'type' => 'padding', 'screen' => 1, 'css' => ['{{element}} .kkart-primary-image-container' => 'margin-top: {{val[0]}}px; margin-right: {{val[1]}}px; margin-bottom: {{val[2]}}px; margin-left: {{val[3]}}px'], ), 'pzoom' => array( 'type' => 'checkbox', 'label' => __('Zoom'), 'default' => '', 'addAttr' => ['{{element}} .kkart-primary-image-container' => 'data-zoom={{pzoom}}'], ), 'slider_controls' => array( 'type' => 'checkbox', 'label' => __('Slider Controls'), 'default' => '', ), 'controls_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .primary-slider-controls [class*="primary-image-"]' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', '{{element}} .pagelayer-btn-holder' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], 'req' => ['!slider_controls' => ''], ), 'controls_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', //'no_val' => 1,// Dont set any value to element 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), 'req' => ['!slider_controls' => ''] ), 'controls_background' => array( 'type' => 'color', 'label' => __('Background Color'), 'defaul' => 'none', 'css' => ['.primary-slider-controls [class*="primary-image-"]' => 'background:{{val}}'], 'show' => ['controls_hover' => ''], 'req' => ['!slider_controls' => '' ] ), 'controls_color' => array( 'type' => 'color', 'label' => __('Color'), 'defaul' => '#000', 'css' => ['.primary-slider-controls [class*="primary-image-"]' => 'color:{{val}}'], 'show' => ['controls_hover' => ''], 'req' => ['!slider_controls' => '' ] ), 'control_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '.primary-slider-controls [class*="primary-image-"]' => 'border-style: {{val}};', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['controls_hover' => ''], 'req' => ['!slider_controls' => '' ] ), 'control_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#42414f', 'css' => ['.primary-slider-controls [class*="primary-image-"]' => 'border-color: {{val}};'], 'show' => ['controls_hover' => ''], 'req' => ['!slider_controls' => '', '!control_border_type' => ''] ), 'control_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['.primary-slider-controls [class*="primary-image-"]' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'show' => ['controls_hover' => ''], 'req' => ['!slider_controls' => '', '!control_border_type' => ''] ), 'control_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['.primary-slider-controls [class*="primary-image-"]' => 'border-top-left-radius: {{val[0]}}px; border-top-right-radius: {{val[1]}}px; border-bottom-right-radius: {{val[2]}}px; border-bottom-left-radius: {{val[3]}}px'], 'show' => ['controls_hover' => ''], 'req' => ['!slider_controls' => '', '!control_border_type' => ''] ), 'controls_background_hover' => array( 'type' => 'color', 'label' => __('Background Hover'), 'defaul' => 'none', 'css' => ['.primary-slider-controls [class*="primary-image-"]:hover' => 'background:{{val}}'], 'show' => ['controls_hover' => 'hover'], 'req' => ['!slider_controls' => '' ] ), 'controls_color_hover' => array( 'type' => 'color', 'label' => __('Color Hover'), 'defaul' => 'none', 'css' => ['.primary-slider-controls [class*="primary-image-"]:hover' => 'color:{{val}}'], 'show' => ['controls_hover' => 'hover'], 'req' => ['!slider_controls' => '' ] ), 'control_border_type_hover' => array( 'type' => 'select', 'label' => __('Hover Border Type'), 'css' => [ '.primary-slider-controls [class*="primary-image-"]:hover' => 'border-style: {{val}};', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['controls_hover' => 'hover'], 'req' => ['!slider_controls' => '' ] ), 'control_border_color_hover' => array( 'type' => 'color', 'label' => __(' Hover Border Color'), 'default' => '#42414f', 'css' => ['.primary-slider-controls [class*="primary-image-"]:hover' => 'border-color: {{val}};'], 'show' => ['controls_hover' => 'hover'], 'req' => ['!slider_controls' => '', '!control_border_type_hover' => ''] ), 'control_border_width_hover' => array( 'type' => 'padding', 'label' => __('Hover Border Width'), 'screen' => 1, 'css' => ['.primary-slider-controls [class*="primary-image-"]:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'show' => ['controls_hover' => 'hover'], 'req' => ['!slider_controls' => '', '!control_border_type_hover' => ''] ), 'control_border_radius_hover' => array( 'type' => 'padding', 'label' => __('Hover Border Radius'), 'screen' => 1, 'css' => ['.primary-slider-controls [class*="primary-image-"]:hover' => 'border-top-left-radius: {{val[0]}}px; border-top-right-radius: {{val[1]}}px; border-bottom-right-radius: {{val[2]}}px; border-bottom-left-radius: {{val[3]}}px'], 'show' => ['controls_hover' => 'hover'], 'req' => ['!slider_controls' => '', '!control_border_type_hover' => ''] ), ), 'styles' => array( 'primary_image' => __('Primary Image'), 'gimg_border_style' => __('Gallery Image Border Style') ) ) ); // Add to cart pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_add_to_cart', array( 'name' => __('Add To Cart'), 'icon' => 'fas fa-cart-arrow-down', 'group' => 'kkart', 'html' => '
{{kkart_cart_form}}
', 'params' => array( 'cart_text' => array( 'type' => 'text', 'label' => __('Cart Text'), 'default' => __('Add To Cart'), ), 'cart_icon' => array( 'type' => 'icon', 'label' => __('Icon'), 'default' => '', ), 'cart_icon_position' => array( 'type' => 'radio', 'label' => __('Alignment'), 'default' => 'kkart-cart-btn-icon-left', 'addClass' => ['{{element}} .kkart-cart-btn-holder' => '{{val}}'], 'list' => array( 'kkart-cart-btn-icon-left' => __('Left'), 'kkart-cart-btn-icon-right' => __('Right') ), ), 'cart_icon_spacing' => array( 'type' => 'slider', 'label' => __('Icon Spacing'), 'min' => 1, 'step' => 1, 'max' => 100, 'default' => 5, 'screen' => 1, 'css' => ['{{element}} .kkart-cart-btn-icon' => 'padding: 0 {{val}}px;'], 'req' => array( '!cart_icon' => 'none' ), ), ), 'cart_quantity' => array( 'show_quantity' => array( 'type' => 'checkbox', 'label' => __('Show Quantity'), 'default' => 'true' ), 'quantity_layout' => array( 'type' => 'select', 'label' => __('Quantity Layout'), 'css' => ['{{element}} .kkart-cart-btn-holder, {{element}} .kkart-product-quantity-holder' => 'display: {{val}};'], 'default' => 'inline-block', 'list' => array( 'block' => __('Block'), 'inline-block' => __('Inline') ), 'req' => ['!show_quantity' => ''], ), 'quantity_box_width' => array( 'type' => 'spinner', 'label' => __('Quantity Box Width'), 'min' => 10, 'step' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => 'width: {{val}}px;'], 'req' => ['!show_quantity' => ''], ), 'quantity_box_height' => array( 'type' => 'spinner', 'label' => __('Quantity Box Height'), 'min' => 15, 'step' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => 'height: {{val}}px;'], 'req' => ['!show_quantity' => ''], ), 'input_background_color' => array( 'type' => 'color', 'label' => __('Input Background Color'), 'default' => '#fff', 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => 'background-color:{{val}}'], 'req' => ['!show_quantity' => ''], 'show' => ['!show_quantity' => ''], ), 'input_text_color' => array( 'type' => 'color', 'label' => __('Input Text Color'), 'default' => '#000', 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => 'color:{{val}}'], 'req' => ['!show_quantity' => ''], 'show' => ['!show_quantity' => ''], ), 'input_button_style' => array( 'type' => 'checkbox', 'label' => __('Input Button Style'), 'default' => '', 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => '-moz-appearance:auto'], 'req' => ['!show_quantity' => ''], 'show' => ['!show_quantity' => ''], ), 'button_width' => array( 'type' => 'spinner', 'label' => __('Button Width'), 'step' => '1', 'default' => '25', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus, {{element}} .kkart-product-quantity .kkart-plus' => 'width:{{val}}px'], 'req' => ['!show_quantity' => ''], 'show' => ['!show_quantity' => ''], ), 'button_height' => array( 'type' => 'spinner', 'label' => __('Button Height'), 'step' => '1', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus, {{element}} .kkart-product-quantity .kkart-plus' => 'height:{{val}}px'], 'req' => ['!show_quantity' => ''], 'show' => ['!show_quantity' => ''], ), 'button_background_color' => array( 'type' => 'color', 'label' => __('Button Background Color'), 'default' => '#fff', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus,{{element}} .kkart-product-quantity .kkart-plus' => 'background-color:{{val}}'], 'req' => ['!show_quantity' => ''], 'show' => ['!show_quantity' => ''], ), 'button_text_color' => array( 'type' => 'color', 'label' => __('Button Text Color'), 'default' => '#000', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus,{{element}} .kkart-product-quantity .kkart-plus' => 'color:{{val}}'], 'req' => ['!show_quantity' => ''], 'show' => ['!show_quantity' => ''], ), 'typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-minus, {{element}} .kkart-plus' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], ), 'quantity_style' => array( 'type' => 'select', 'label' => __('Separate Box'), 'addClass' => ['{{element}} .kkart-product-quantity' => 'kkart-quantity-style-{{val}}'], 'list' => array( 'rounded' => __('Rounded'), '' => __('Boxed') ), ), 'quantity_border_color' =>array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#efefef', 'css' => ['{{element}} .kkart-product-quantity' => 'border-color:{{val}}'], 'show' => ['quantity_style' => ''], ), 'quantity_border_size' =>array( 'type' => 'padding', 'label' => __('Border Size'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'show' => ['quantity_style' => ''], ), 'quantity_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity' => 'border-radius: {{val[0]}}px; {{val[1]}}px {{val[2]}}px {{val[3]}}px'], 'show' => ['quantity_style' => ''], ), 'show_seperator' => array( 'type' => 'checkbox', 'label' => __('Show Seperator'), 'default' => '', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus' => 'border-right: 1px solid #efefef;', '{{element}} .kkart-product-quantity .plus' => 'border-left: 1px solid #efefef;'], 'show' => ['quantity_style' => ''], ), 'seperator_border_color' => array( 'type' => 'color', 'label' => __('Seperator Border Color'), 'default' => '#efefef', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus' => 'border-right-color: {{val}};', '{{element}} .kkart-product-quantity .kkart-plus' => 'border-left-color: {{val}};'], 'req' => ['quantity_style' => '','!show_seperator' => ''], ), 'seperator_border_size' =>array( 'type' => 'spinner', 'label' => __('Seperator Border Size'), 'min' => 1, 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity .kkart-minus' => 'border-right-width: {{val}}px;', '{{element}} .kkart-product-quantity .kkart-plus' => 'border-left-width: {{val}}px;'], 'req' => ['quantity_style' => '','!show_seperator' => ''], ), 'spacing' => array( 'type' => 'spinner', 'label' => __('Spacing'), 'min' => '2', 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'margin-left:{{val}}px; margin-right:{{val}}px;'], 'req' => ['quantity_style' => 'rounded'], ), 'input_border_type' => array( 'type' => 'select', 'label' => __('Input Border Type'), 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-style:{{val}}'], 'req' => ['quantity_style' => 'rounded'], ), 'input_border_color' => array( 'type' => 'color', 'label' => __('Input Border Color'), 'default' => '#fff', 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-color:{{val}}'], 'req' => ['quantity_style' => 'rounded', '!input_border_type' => ''], ), 'input_border_width' => array( 'type' => 'padding', 'label' => __('Input Border Width'), 'screen' => '1', 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-top-width:{{val[0]}}px; border-left-width:{{val[1]}}px; border-bottom-width:{{val[2]}}px; border-right-width:{{val[3]}}px'], 'req' => ['quantity_style' => 'rounded', '!input_border_type' => ''], ), 'input_border_radius' => array( 'type' => 'padding', 'label' => __('Input Border Radius'), 'screen' => '1', 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-top-left-radius:{{val[0]}}px; border-top-right-radius:{{val[1]}}px; border-bottom-right-radius:{{val[2]}}px; border-bottom-left-radius:{{val[3]}}px'], 'req' => ['quantity_style' => 'rounded', '!input_border_type' => ''], ), 'button_border_type' => array( 'type' => 'select', 'label' => __('Button Border Type'), 'default' => 'solid', 'list' => [ 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-style:{{val}}'], 'req' => ['quantity_style' => 'rounded'], ), 'button_border_color' => array( 'type' => 'color', 'label' => __('Button Border Color'), 'default' => '#000', 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-color:{{val}}'], 'req' => ['quantity_style' => 'rounded'], ), 'button_border_width' => array( 'type' => 'padding', 'label' => __('Button Border Width'), 'screen' => '1', 'default' => '2,2,2,2', 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-top-width:{{val[0]}}px; border-left-width:{{val[1]}}px; border-bottom-width:{{val[2]}}px; border-right-width:{{val[3]}}px;'], 'req' => ['quantity_style' => 'rounded'], ), 'button_border_radius' => array( 'type' => 'padding', 'label' => __('Button Border Radius'), 'screen' => '1', 'default' => '25,25,25,25', 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-top-left-radius:{{val[0]}}px; border-top-right-radius:{{val[1]}}px; border-bottom-right-radius:{{val[2]}}px; border-bottom-left-radius:{{val[3]}}px'], 'req' => ['quantity_style' => 'rounded'], ), ), 'cart_btn_style' => array( 'btn_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-cart-btn-text' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', '{{element}} .pagelayer-btn-holder' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], ), 'cart_type' => array( 'type' => 'select', 'label' => __('Button Type'), 'default' => 'pagelayer-btn-default', 'addClass' => ['{{element}} .kkart-cart-btn-holder' => '{{val}}'], 'list' => array( 'pagelayer-btn-default' => __('Default'), 'pagelayer-btn-primary' => __('Primary'), 'pagelayer-btn-secondary' => __('Secondary'), 'pagelayer-btn-success' => __('Success'), 'pagelayer-btn-info' => __('Information'), 'pagelayer-btn-warning' => __('Warning'), 'pagelayer-btn-danger' => __('Danger'), 'pagelayer-btn-dark' => __('Dark'), 'pagelayer-btn-light' => __('Light'), 'pagelayer-btn-link' => __('Link'), 'pagelayer-btn-custom' => __('Custom') ), ), 'cart_size' => array( 'type' => 'select', 'label' => __('Button Size'), 'default' => 'pagelayer-btn-small', 'addClass' => ['{{element}} .kkart-cart-btn-holder' => '{{val}}'], 'list' => array( 'pagelayer-btn-mini' => __('Mini'), 'pagelayer-btn-small' => __('Small'), 'pagelayer-btn-large' => __('Large'), 'pagelayer-btn-extra-large' => __('Extra Large'), 'pagelayer-btn-double-large' => __('Double Large'), 'pagelayer-btn-custom' => __('Custom'), ) ), 'btn_custom_size' => array( 'type' => 'spinner', 'label' => __('Button Custom Size'), 'min' => 1, 'step' => 1, 'max' => 100, 'default' => 5, 'screen' => 1, 'css' => ['{{element}} .kkart-cart-btn-holder' => 'padding: calc({{val}}px / 2) {{val}}px;'], 'req' => array( 'cart_size' => ['pagelayer-btn-custom'], ), ), 'btn_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', //'no_val' => 1,// Dont set any value to element 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), 'req' => array( 'cart_type' => ['pagelayer-btn-custom'], ), ), 'btn_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'default' => '#818a91', 'css' => [ '{{element}} .kkart-cart-btn-holder' => 'background-color: {{val}};', ], 'req' => array( 'cart_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => '' ), ), 'btn_color' => array( 'type' => 'color', 'label' => __('Button Color'), 'default' => '#ffffff', 'css' => ['{{element}} .kkart-cart-btn-holder' => 'color: {{val}};'], 'req' => array( 'cart_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => '' ), ), 'btn_hover_delay' => array( 'type' => 'spinner', 'label' => __('Button Hover Delay'), 'desc' => __('Time to delay the hover in ms'), 'min' => 0, 'step' => 100, 'max' => 5000, 'default' => 400, 'css' => ['{{element}} .kkart-cart-btn-holder' => '-webkit-transition: all {{val}}ms !important; transition: all {{val}}ms !important;'], 'show' => array( 'cart_type' => ['pagelayer-btn-custom'], 'btn_hover' => 'hover' ), ), 'btn_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Hover Color'), 'default' => '', 'css' => [ '{{element}} .kkart-cart-btn-holder:hover' => 'background-color: {{val}};', ], 'req' => array( 'cart_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => 'hover', ), ), 'btn_color_hover' => array( 'type' => 'color', 'label' => __('Hover Color'), 'default' => '', 'css' => ['{{element}} .kkart-cart-btn-holder:hover' => 'color: {{val}};'], 'req' => array( 'cart_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => 'hover' ), ), 'btn_shadow' => array( 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} .kkart-cart-btn-holder' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[4]}}px {{val[3]}} {{val[5]}} !important;'], ), 'btn_shadow_hover' => array( // This is actually box shadow hover 'type' => 'box_shadow', 'label' => __('Box Shadow Hover'), 'css' => ['{{element}} .kkart-cart-btn-holder' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}} !important;'], ), ), 'cart_border_style' => [ 'btn_bor_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', //'no_val' => 1,// Dont set any value to element 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-cart-btn-holder' => 'border-style: {{val}};', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-cart-btn-holder' => 'border-color: {{val}};'], 'req' => array( '!btn_border_type' => '' ), 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-cart-btn-holder' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => [ '!btn_border_type' => '' ], 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-cart-btn-holder' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!btn_border_type' => '', ), 'show' => array( 'btn_bor_hover' => '', ), ), 'btn_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-cart-btn-holder:hover' => 'border-style: {{val}}' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color Hover'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-cart-btn-holder:hover' => 'border-color: {{val}};'], 'req' => array( '!btn_border_type_hover' => '' ), 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width Hover'), 'screen' => 1, 'css' => [ '{{element}} .kkart-cart-btn-holder:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px;' ], 'req' => [ '!btn_border_type_hover' => '' ], 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius Hover'), 'screen' => 1, 'css' => ['{{element}} .kkart-cart-btn-holder:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!btn_border_type_hover' => '', ), 'show' => array( 'btn_bor_hover' => 'hover', ), ), ], 'styles' => array( 'cart_quantity' => __('Cart Quantity'), 'cart_btn_style' => __('Cart Button Style'), 'cart_border_style' => __('Cart Border Style'), ) ) ); // Cart items holder pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_items', array( 'name' => __('Cart Items'), 'icon' => 'fas fa-cart-plus', 'group' => 'kkart cart', 'func' => 'kkart_sc_cart_items', 'has_group' => [ 'section' => 'params', 'prop' => 'elements', ], 'holder' => '.kkart-cart-items-holder', 'html' => '
', 'params' => array( 'elements' => array( 'type' => 'group', 'label' => __('Inner Row'), 'sc' => PAGELAYER_SC_PREFIX.'_inner_row', // a.k.a the item being multiplied by the count 'count' => 1, 'item_label' => array( 'default' => __('Inner Row'), ), 'item_atts' => [], // orderwise array of attrbutes to be set as per the count given 'inner_content' => [ // This is the content within each item which is going to the created i.e. within each SC. This only use for inner rows ['pl_col' => [ 'inner_content' => [ ['pl_kkart_archive_thumb' => []] ] ] ], ['pl_col' => [ 'inner_content' => [ ['pl_kkart_title' => ['atts' => ['typo' => ',20,,700,,,Solid,,,,', 'link' => 'true']]], ['pl_kkart_cart_price' => ['atts' => ['price_type' => 'product_sub_total']]], ['pl_kkart_cart_variable' => []], ['pl_kkart_cart_item_quantity' => []], ['pl_kkart_cart_update' => ['atts' => ['ele_custom_pos' => 'true', 'ele_width' => 'initial']]], ['pl_kkart_cart_item_remove' => ['atts' => ['ele_custom_pos' => 'true', 'ele_width' => 'initial']]], ], ] ], ], 'hide' => 1, ), ), ) ); // Cart item counter pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_variable', array( 'name' => __('Cart Variable Meta'), 'group' => 'kkart cart', 'func' => 'kkart_sc_cart_variable', 'html' => '
{{variable_meta}}
', 'params' => array( 'color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-cart-variables-holder' => 'color: {{val}};'], ), ), ) ); // Cart item counter pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_item_quantity', array( 'name' => __('Cart Item Quantity'), 'group' => 'kkart cart', 'icon' => 'fas fa-luggage-cart', 'func' => 'kkart_sc_cart_item_quantity', 'html' => '
{{form_html}}
', 'params' => array( 'quantity_box_width' => array( 'type' => 'spinner', 'label' => __('Quantity Box Width'), 'min' => 10, 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => 'width: {{val}}px;'], ), 'quantity_box_height' => array( 'type' => 'spinner', 'label' => __('Quantity Box Height'), 'min' => 15, 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity' => 'height: {{val}}px;'], ), 'input_background_color' => array( 'type' => 'color', 'label' => __('Input Background Color'), 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => 'background-color:{{val}}'], ), 'input_text_color' => array( 'type' => 'color', 'label' => __('Input Text Color'), 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => 'color:{{val}}'], ), 'input_button_style' => array( 'type' => 'checkbox', 'label' => __('Input Button Style'), 'default' => '', 'css' => ['{{element}} .kkart-product-quantity input[type="number"]' => '-moz-appearance:auto'], // Not working ), 'button_width' => array( 'type' => 'spinner', 'label' => __('Button Width'), 'default' => '25', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus, {{element}} .kkart-product-quantity .kkart-plus' => 'width:{{val}}px'], ), 'button_background_color' => array( 'type' => 'color', 'label' => __('Button Background Color'), 'css' => ['{{element}} .kkart-product-quantity .kkart-minus,{{element}} .kkart-product-quantity .kkart-plus' => 'background-color:{{val}}'], ), 'button_text_color' => array( 'type' => 'color', 'label' => __('Button Color'), 'css' => ['{{element}} .kkart-minus, {{element}} .kkart-plus' => 'color:{{val}}'], ), 'typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-minus, {{element}} .kkart-plus' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], ), 'quantity_style' => array( 'type' => 'select', 'label' => __('Separate Box'), 'addClass' => ['{{element}} .kkart-product-quantity' => 'kkart-quantity-style-{{val}}'], 'list' => array( 'rounded' => __('Rounded'), '' => __('Boxed') ), ), 'quantity_border_color' =>array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#efefef', 'css' => ['{{element}} .kkart-product-quantity' => 'border-color:{{val}}'], 'show' => ['quantity_style' => ''], ), 'quantity_border_size' =>array( 'type' => 'padding', 'label' => __('Border Size'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'show' => ['quantity_style' => ''], ), 'quantity_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity' => 'border-radius: {{val[0]}}px; {{val[1]}}px {{val[2]}}px {{val[3]}}px'], 'show' => ['quantity_style' => ''], ), 'show_seperator' => array( 'type' => 'checkbox', 'label' => __('Show Seperator'), 'default' => '', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus' => 'border-right: 1px solid #efefef;', '{{element}} .kkart-product-quantity .plus' => 'border-left: 1px solid #efefef;'], 'show' => ['quantity_style' => ''], ), 'seperator_border_color' => array( 'type' => 'color', 'label' => __('Seperator Border Color'), 'default' => '#efefef', 'css' => ['{{element}} .kkart-product-quantity .kkart-minus' => 'border-right-color: {{val}};', '{{element}} .kkart-product-quantity .kkart-plus' => 'border-left-color: {{val}};'], 'req' => ['quantity_style' => '','!show_seperator' => ''], ), 'seperator_border_size' =>array( 'type' => 'spinner', 'label' => __('Seperator Border Size'), 'min' => 1, 'screen' => 1, 'css' => ['{{element}} .kkart-product-quantity .kkart-minus' => 'border-right-width: {{val}}px;', '{{element}} .kkart-product-quantity .kkart-plus' => 'border-left-width: {{val}}px;'], 'req' => ['quantity_style' => '','!show_seperator' => ''], ), 'spacing' => array( 'type' => 'spinner', 'label' => __('Spacing'), 'min' => '2', 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'margin-left:{{val}}px; margin-right:{{val}}px;'], 'req' => ['quantity_style' => 'rounded'], ), 'input_border_type' => array( 'type' => 'select', 'label' => __('Input Border Type'), 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-style:{{val}}'], 'req' => ['quantity_style' => 'rounded'], ), 'input_border_color' => array( 'type' => 'color', 'label' => __('Input Border Color'), 'default' => '#fff', 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-color:{{val}}'], 'req' => ['quantity_style' => 'rounded', '!input_border_type' => ''], ), 'input_border_width' => array( 'type' => 'padding', 'label' => __('Input Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-top-width:{{val[0]}}px; border-left-width:{{val[1]}}px; border-bottom-width:{{val[2]}}px; border-right-width:{{val[3]}}px'], 'req' => ['quantity_style' => 'rounded', '!input_border_type' => ''], ), 'input_border_radius' => array( 'type' => 'padding', 'label' => __('Input Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity-style-rounded input[type="number"]' => 'border-top-left-radius:{{val[0]}}px; border-top-right-radius:{{val[1]}}px; border-bottom-right-radius:{{val[2]}}px; border-bottom-left-radius:{{val[3]}}px'], 'req' => ['quantity_style' => 'rounded', '!input_border_type' => ''], ), 'button_border_type' => array( 'type' => 'select', 'label' => 'button_border_type', 'default' => 'solid', 'list' => [ 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-style:{{val}}'], 'req' => ['quantity_style' => 'rounded'], ), 'button_border_color' => array( 'type' => 'color', 'label' => __('Button Border Color'), 'default' => '#000', 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-color:{{val}}'], 'req' => ['quantity_style' => 'rounded'], ), 'button_border_width' => array( 'type' => 'padding', 'label' => __('Button Border Width'), 'screen' => '1', 'default' => '2,2,2,2', 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-top-width:{{val[0]}}px; border-left-width:{{val[1]}}px; border-bottom-width:{{val[2]}}px; border-right-width:{{val[3]}}px;'], 'req' => ['quantity_style' => 'rounded'], ), 'button_border_radius' => array( 'type' => 'padding', 'label' => __('Button Border Radius'), 'screen' => '1', 'default' => '25,25,25,25', 'css' => ['{{element}} .kkart-quantity-style-rounded .kkart-minus, {{element}} .kkart-quantity-style-rounded .kkart-plus' => 'border-top-left-radius:{{val[0]}}px; border-top-right-radius:{{val[1]}}px; border-bottom-right-radius:{{val[2]}}px; border-bottom-left-radius:{{val[3]}}px'], 'req' => ['quantity_style' => 'rounded'], ), ), ) ); // Cart item Remove pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_item_remove', array( 'name' => __('Cart Item Remove'), 'group' => 'kkart cart', 'icon' => 'far fa-trash-alt', 'func' => 'kkart_sc_cart_item_remove', 'html' => ' {{text}} ', 'params' => array( 'icon' => array( 'type' => 'icon', 'label' => __('Icon'), 'default' => 'fas fa-trash-alt', ), 'text' => array( 'type' => 'text', 'label' => __('Text'), ), 'color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-item-remove-link' => 'color:{{val}}' ], ), 'padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .pagelayer-btn-icon' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-item-remove-link' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'spacing_between' => array( 'type' => 'slider', 'label' => __('Spacing Between'), 'css' => ['{{element}} .pagelayer-btn-icon' => 'padding-right:{{val}}px' ], ), ), ) ); // Cart item update pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_update', array( 'name' => __('Cart Update Button'), 'group' => 'kkart cart', 'func' => 'kkart_sc_cart_item_update', 'html' => ' ', 'params' => array( 'icon' => array( 'type' => 'icon', 'label' => __('Icon'), ), 'text' => array( 'type' => 'text', 'label' => __('Text'), 'default' => __('Update Cart'), ), 'bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .kkart-items-update' => 'background-color:{{val}}' ], ), 'color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-items-update' => 'color:{{val}}' ], ), 'padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-items-update' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-items-update' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'spacing_between' => array( 'type' => 'slider', 'label' => __('Spacing Between'), 'css' => ['{{element}} .pagelayer-btn-icon' => 'padding-right:{{val}}px' ], ), ), ) ); // Cart item count pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_item_count', array( 'name' => __('Cart Item Count'), 'group' => 'kkart cart', //'use_inside' => ['pl_kkart_archive_item'], 'html' => '
{{before}}{{item_count}}{{after}}
', 'params' => array( 'before' => array( 'type' => 'text', 'label' => __('Before'), ), 'after' => array( 'type' => 'text', 'label' => __('After'), ), 'title_colors' => array( 'type' => 'radio', 'label' => __('Colors'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'color' => array( 'type' => 'color', 'label' => __('Color'), 'default' => '#0986c0', 'css' => ['{{element}} .kkart-cart-item-count, {{element}} .kkart-cart-item-count *' => 'color:{{val}}'], 'show' => ['title_colors' => ''] ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-cart-item-count' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], 'show' => ['title_colors' => ''] ), 'color_hover' => array( 'type' => 'color', 'label' => __('Color'), 'default' => '#0986c0', 'css' => ['{{element}} .kkart-cart-item-count:hover, {{element}} .kkart-cart-item-count:hover *' => 'color:{{val}}'], 'show' => ['title_colors' => 'hover'] ), 'typo_hover' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-cart-item-count:hover' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], 'show' => ['title_colors' => 'hover'] ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'list' => [ 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ], 'css' => ['{{element}} .kkart-cart-item-count' => 'text-align: {{val}}'], ), ) ) ); // Cart item totals pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_price', array( 'name' => __('Cart Prices'), 'group' => 'kkart cart', 'func' => 'kkart_sc_cart_price', 'html' => '
{{title}}
{{item_price}}
', 'params' => array( 'title_hide' => array( 'type' => 'checkbox', 'label' => __('Hide title'), ), 'title' => array( 'label' => __('Price'), 'type' => 'text', 'default' => __('Price'), 'req' => ['title_hide' => ''] ), 'price_type' => array( 'type' => 'select', 'label' => __('Price Type'), 'default' => 'price', 'list' => [ 'price' => __('Price'), 'sub_total' => __('Sub Total'), 'grand_total' => __('Grand Total '), 'all_items_total' => __('All Items Total'), 'discount' => __('Discount'), 'delivery_charges' => __('Delivery Charges'), 'product_sub_total' => __('Product Sub Total'), 'tax' => __('Tax'), ], ), ), ) ); pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_product_variation', array( 'name' => __('Variation'), 'group' => 'kkart', 'func' => 'kkart_sc_product_variation', 'not_visible' => 1, 'html' => '
{{product_variation_html}}
', 'params' => array( 'selection_type' =>array( 'type' => 'select', 'label' => __('Selection Type'), 'default' => 'dropdown', 'list' => array( 'dropdown' => __('Dropdown'), 'checkbox' => __('Checkbox') ), ), 'checkbox_options' => array( 'type' => 'select', 'label' => __('Checkbox Style'), 'default' => 'text', 'list' => array( 'text' => __('Text'), 'image' => __('Image') ), 'req' => [ 'selection_type' => 'checkbox' ] ) ) ) ); pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_cart_price_holder', array( 'name' => __('Cart Price Holder'), 'group' => 'kkart_cart', 'icon' => 'fas fa-dollar-sign', 'func' => 'kkart_sc_cart_prices', 'has_group' => [ 'section' => 'params', 'prop' => 'elements' ], 'holder' => '.kkart_cart_price_holder', 'html' => '
'. kkart_checkout_coupon_form(array(), false).'
Checkout', 'params' => array( 'hide_coupon'=>array( 'type' => 'checkbox', 'label' => __('Hide Coupon'), ), 'coupon_position'=>array( 'type' => 'checkbox', 'label' => __('Coupon after pricing'), 'css' => [ '{{element}} .kkart_cart_price_holder' => 'order:-1'], 'show' => ['!hide_coupon' => 'true'] ), 'elements'=> array( 'type' => 'group', 'label' => __('Prices'), 'sc' => PAGELAYER_SC_PREFIX.'_kkart_cart_price', 'count' => 6, 'item_label' => array( 'default' => __('Price'), 'param' => 'title' ), 'item_atts' => array( ['title' => 'Sub Total', 'price_type' => 'sub_total'], ['title' => 'Items Total', 'price_type' => 'all_items_total'], ['title' => 'Delivery Charges', 'price_type' => 'delivery_charges'], ['title' => 'Discount', 'price_type' => 'discount'], ['title' => 'Tax', 'price_type' => 'tax'], ['title' => 'Grand Total', 'price_type' => 'grand_total'], ), 'hide' => 1 ) ), 'checkout_button' => array( 'hide_checkout' => array( 'type' => 'checkbox', 'label' => __('Hide Checkout Button'), 'css' => [ '{{element}} .kkart-cart-checkout-button' => 'display:none'] ), 'checkout_btn_colors' => array( 'type' => 'radio', 'label' => __('Button Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'checkout_btn_bg'=> array( 'label' => __('Background Color'), 'type' => 'color', 'css' => ['{{element}} .kkart-cart-checkout-button' => 'background-color:{{val}}'], 'show' => ['checkout_btn_colors' => ''] ), 'checkout_btn_color'=> array( 'label' => __('Color'), 'type' => 'color', 'css' => ['{{element}} .kkart-cart-checkout-button' => 'color:{{val}}'], 'show' => ['checkout_btn_colors' => ''] ), 'checkout_btn_hover_bg'=> array( 'label' => __('Background Color'), 'type' => 'color', 'css' => ['{{element}} .kkart-cart-checkout-button:hover' => 'background-color:{{val}}'], 'show' => ['checkout_btn_colors' => 'hover'] ), 'checkout_btn_hover_color'=> array( 'label' => __('Color'), 'type' => 'color', 'css' => ['{{element}} .kkart-cart-checkout-button:hover' => 'color:{{val}}'], 'show' => ['checkout_btn_colors' => 'hover'] ), 'checkout_btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-cart-checkout-button' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'checkout_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!checkout_btn_border_type' => ''] ), 'checkout_btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-cart-checkout-button' => 'border-color: {{val}};'], 'req' => ['!checkout_btn_border_type' => ''], 'show' => ['checkout_border_colors' => ''] ), 'checkout_btn_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .kkart-cart-checkout-button:hover' => 'border-color: {{val}};'], 'req' => ['!checkout_btn_border_type' => ''], 'show' => ['checkout_border_colors' => 'hover'] ), 'checkout_btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-cart-checkout-button' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!checkout_btn_border_type' => ''] ), 'checkout_btn_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-cart-checkout-button' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'checkout_btn_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-cart-checkout-button' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'checkout_btn_display' => array( 'type' => 'select', 'label' => __('Display'), 'screen' => 1, 'default' => '', 'css' => ['{{element}} .kkart-cart-checkout-button' => 'display:{{val}}'], 'list' => array( '' => __('Full'), 'inline-block' => __('Inline'), ), ), 'checkout_btn_width' => array( 'type' => 'slider', 'label' => __('Width'), 'default' => 100, 'min' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} a.kkart-cart-checkout-button' => 'width:{{val}}%'], ), ), 'styles' => array( 'checkout_button' => __('Checkout Button') ) ) ); // Buy now Button pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_buy_now', array( 'name' => __('Buy Now'), 'icon' => 'fa fa-shopping-basket', 'group' => 'kkart', 'func' => 'kkart_sc_buy_now', 'use_inside' => ['pl_kkart_archive_item'], 'html' => '', 'params' => array( 'buy_now_text' => array( 'type' => 'text', 'label' => __('Text'), 'default' => 'Buy Now', ), 'full_width' => array( 'type' => 'checkbox', 'label' => __('Stretch'), 'screen' => 1, 'css' => ['{{element}} a' => 'width: 100%; text-align: center;'] ), 'btn_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-buy-now' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'default' => 'left', 'screen' => 1, 'css' => 'text-align: {{val}}', 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right') ), 'req' => array( 'full_width' => '' ) ), ), 'btn_style' => [ 'type' => array( 'type' => 'select', 'label' => __('Button Type'), 'default' => 'pagelayer-btn-default', 'list' => array( 'pagelayer-btn-default' => __('Default'), 'pagelayer-btn-primary' => __('Primary'), 'pagelayer-btn-secondary' => __('Secondary'), 'pagelayer-btn-success' => __('Success'), 'pagelayer-btn-info' => __('Information'), 'pagelayer-btn-warning' => __('Warning'), 'pagelayer-btn-danger' => __('Danger'), 'pagelayer-btn-dark' => __('Dark'), 'pagelayer-btn-light' => __('Light'), 'pagelayer-btn-link' => __('Link'), '' => __('Custom') ), 'addClass' => ['{{element}} .kkart-buy-now' => '{{val}}'], ), 'size' => array( 'type' => 'select', 'label' => __('Size'), 'default' => '', 'list' => array( 'pagelayer-btn-mini' => __('Mini'), 'pagelayer-btn-small' => __('Small'), 'pagelayer-btn-large' => __('Large'), 'pagelayer-btn-extra-large' => __('Extra Large'), 'pagelayer-btn-double-large' => __('Double Large'), '' => __('Custom'), ), 'addClass' => ['{{element}} .kkart-buy-now' => '{{val}}'], ), 'btn_custom_size' => array( 'type' => 'spinner', 'label' => __('Custom Size'), 'min' => 1, 'max' => 100, 'default' => 10, 'screen' => 1, 'css' => ['{{element}} .kkart-buy-now' => 'padding: calc({{val}}px / 2) {{val}}px;'], 'req' => ['size' => ''], ), 'btn_hover' => array( 'type' => 'radio', 'label' => __('State'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), 'req' => ['type' => ''], ), 'btn_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'default' => '#818a91', 'css' => ['{{element}} .kkart-buy-now' => 'background-color: {{val}};'], 'req' => ['type' => ''], 'show' => ['btn_hover' => ''], ), 'btn_color' => array( 'type' => 'color', 'label' => __('Button Color'), 'default' => '#ffffff', 'css' => ['{{element}} .kkart-buy-now' => 'color: {{val}};'], 'req' => ['type' => ''], 'show' => ['btn_hover' => ''], ), 'btn_hover_delay' => array( 'type' => 'spinner', 'label' => __('Button Hover Delay'), 'desc' => __('Time to delay the hover in ms'), 'min' => 0, 'step' => 100, 'max' => 5000, 'default' => 400, 'css' => ['{{element}} .kkart-buy-now' => '-webkit-transition: all {{val}}ms !important; transition: all {{val}}ms !important;'], 'show' => ['type' => '', 'btn_hover' => 'hover'], ), 'btn_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Hover Color'), 'css' => ['{{element}} .kkart-buy-now:hover, {{element}} .pagelayer-btn-anim-slide:after' => 'background-color: {{val}};'], 'req' => ['type' => ''], 'show' =>['btn_hover' => 'hover'], ), 'btn_color_hover' => array( 'type' => 'color', 'label' => __('Hover Color'), 'css' => ['{{element}} .kkart-buy-now:hover' => 'color: {{val}};'], 'req' => ['type' => ''], 'show' => ['btn_hover' => 'hover'], ), 'btn_shadow' => [ 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} .kkart-buy-now' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[4]}}px {{val[3]}} {{val[5]}} !important;'], ], 'btn_shadow_hover' => [ // This is actually box shadow hover 'type' => 'box_shadow', 'label' => __('Box Shadow Hover'), 'css' => ['{{element}} .kkart-buy-now:hover' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}} !important;'], ], ], 'border_style' => [ 'btn_bor_hover' => array( 'type' => 'radio', 'label' => __('State'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .kkart-buy-now' => 'border-style: {{val}};'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['btn_bor_hover' => ''], ), 'btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-buy-now' => 'border-color: {{val}};'], 'req' => ['!btn_border_type' => ''], 'show' => ['btn_bor_hover' => ''], ), 'btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-buy-now' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => [ '!btn_border_type' => '' ], 'show' => ['btn_bor_hover' => ''], ), 'btn_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-buy-now' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!btn_border_type' => ''], 'show' => ['btn_bor_hover' => ''], ), 'btn_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .kkart-buy-now:hover' => 'border-style: {{val}}'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['btn_bor_hover' => 'hover'], ), 'btn_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color Hover'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-buy-now:hover' => 'border-color: {{val}};'], 'req' => ['!btn_border_type_hover' => ''], 'show' => ['btn_bor_hover' => 'hover'], ), 'btn_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width Hover'), 'screen' => 1, 'css' => [ '{{element}} .kkart-buy-now:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px;' ], 'req' => ['!btn_border_type_hover' => ''], 'show' => ['btn_bor_hover' => 'hover'], ), 'btn_border_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius Hover'), 'screen' => 1, 'css' => ['{{element}} .kkart-buy-now:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!btn_border_type_hover' => ''], 'show' => ['btn_bor_hover' => 'hover'], ), ], 'icon_style' => [ 'buy_now_icon' => array( 'type' => 'icon', 'label' => __('Icon'), ), 'icon_position' => array( 'type' => 'radio', 'label' => __('Alignment'), 'list' => array( 'kkart-buy-now-icon-left' => __('Left'), '' => __('Right') ), 'addClass' => ['{{element}} .kkart-buy-now' => '{{val}}'], 'req' => ['!buy_now_icon' => 'none'], ), 'icon_spacing' => array( 'type' => 'slider', 'label' => __('Icon Spacing'), 'min' => 1, 'max' => 100, 'default' => 5, 'screen' => 1, 'css' => ['{{element}} .kkart-buy-now-icon' => 'padding: 0 {{val}}px;'], 'req' => ['!buy_now_icon' => 'none'], ), ], 'styles' => array( 'btn_style' => __('Button Styles'), 'border_style' => __('Border Style'), 'icon_style' => __('Icon Style') ), ) ); // Cart Proceed Button pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_checkout_proceed_btn', array( 'name' => __('Checkout Proceed Button'), 'group' => 'kkart cart', 'html' => '', 'params' => array( 'checkout_proceed_text' => array( 'type' => 'text', 'label' => __('Text'), 'default' => 'Proceed To Checkout', ), 'full_width' => array( 'type' => 'checkbox', 'label' => __('Stretch'), 'screen' => 1, 'css' => ['{{element}} a' => 'width: 100%; text-align: center;'] ), 'btn_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-checkout-proceed' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', '{{element}} .kkart-checkout-proceed-holder' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'default' => 'left', 'screen' => 1, 'css' => 'text-align: {{val}}', 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right') ), 'req' => array( 'full_width' => '' ) ), ), 'btn_style' => [ 'type' => array( 'type' => 'select', 'label' => __('Button Type'), 'default' => 'pagelayer-btn-default', 'list' => array( 'pagelayer-btn-default' => __('Default'), 'pagelayer-btn-primary' => __('Primary'), 'pagelayer-btn-secondary' => __('Secondary'), 'pagelayer-btn-success' => __('Success'), 'pagelayer-btn-info' => __('Information'), 'pagelayer-btn-warning' => __('Warning'), 'pagelayer-btn-danger' => __('Danger'), 'pagelayer-btn-dark' => __('Dark'), 'pagelayer-btn-light' => __('Light'), 'pagelayer-btn-link' => __('Link'), '' => __('Custom') ), 'addClass' => ['{{element}} .kkart-checkout-proceed' => '{{val}}'], ), 'size' => array( 'type' => 'select', 'label' => __('Size'), 'default' => 'pagelayer-btn-large', 'list' => array( 'pagelayer-btn-mini' => __('Mini'), 'pagelayer-btn-small' => __('Small'), 'pagelayer-btn-large' => __('Large'), 'pagelayer-btn-extra-large' => __('Extra Large'), 'pagelayer-btn-double-large' => __('Double Large'), '' => __('Custom'), ), 'addClass' => ['{{element}} .kkart-checkout-proceed' => '{{val}}'], ), 'btn_custom_size' => array( 'type' => 'spinner', 'label' => __('Custom Size'), 'min' => 1, 'step' => 1, 'max' => 100, 'default' => 5, 'screen' => 1, 'css' => ['{{element}} .kkart-checkout-proceed' => 'padding: calc({{val}}px / 2) {{val}}px;'], 'req' => array( 'size' => '', ), ), 'btn_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', //'no_val' => 1,// Dont set any value to element 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), 'req' => array( 'type' => '', ), ), 'btn_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'default' => '#818a91', 'css' => [ '{{element}} .kkart-checkout-proceed' => 'background-color: {{val}};', ], 'req' => array( 'type' => '', ), 'show' => array( 'btn_hover' => '' ), ), 'btn_color' => array( 'type' => 'color', 'label' => __('Button Color'), 'default' => '#ffffff', 'css' => ['{{element}} .kkart-checkout-proceed' => 'color: {{val}};'], 'req' => array( 'type' => '', ), 'show' => array( 'btn_hover' => '' ), ), 'btn_hover_delay' => array( 'type' => 'spinner', 'label' => __('Button Hover Delay'), 'desc' => __('Time to delay the hover in ms'), 'min' => 0, 'step' => 100, 'max' => 5000, 'default' => 400, 'css' => ['{{element}} .kkart-checkout-proceed' => '-webkit-transition: all {{val}}ms !important; transition: all {{val}}ms !important;'], 'show' => array( 'type' => '', 'btn_hover' => 'hover' ), ), 'btn_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Hover Color'), 'default' => '', 'css' => [ '{{element}} .kkart-checkout-proceed:hover, {{element}} .pagelayer-btn-anim-slide:after' => 'background-color: {{val}};', ], 'req' => array( 'type' => '', ), 'show' => array( 'btn_hover' => 'hover', ), ), 'btn_color_hover' => array( 'type' => 'color', 'label' => __('Hover Color'), 'css' => ['{{element}} .kkart-checkout-proceed:hover' => 'color: {{val}};'], 'req' => array( 'type' => '', ), 'show' => array( 'btn_hover' => 'hover' ), ), 'btn_shadow' => [ 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} .kkart-checkout-proceed' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[4]}}px {{val[3]}} {{val[5]}} !important;'], ], 'btn_shadow_hover' => [ // This is actually box shadow hover 'type' => 'box_shadow', 'label' => __('Box Shadow Hover'), 'css' => ['{{element}} .kkart-checkout-proceed:hover' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}} !important;'], ], ], 'border_style' => [ 'btn_bor_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', //'no_val' => 1,// Dont set any value to element 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .kkart-checkout-proceed' => 'border-style: {{val}};'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-checkout-proceed' => 'border-color: {{val}};'], 'req' => array( '!btn_border_type' => '' ), 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-checkout-proceed' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => [ '!btn_border_type' => '' ], 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-checkout-proceed' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!btn_border_type' => '', ), 'show' => array( 'btn_bor_hover' => '', ), ), 'btn_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .kkart-checkout-proceed:hover' => 'border-style: {{val}}'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color Hover'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-checkout-proceed:hover' => 'border-color: {{val}};'], 'req' => array( '!btn_border_type_hover' => '' ), 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width Hover'), 'screen' => 1, 'css' => [ '{{element}} .kkart-checkout-proceed:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px;' ], 'req' => [ '!btn_border_type_hover' => '' ], 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius Hover'), 'screen' => 1, 'css' => ['{{element}} .kkart-checkout-proceed:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!btn_border_type_hover' => '', ), 'show' => array( 'btn_bor_hover' => 'hover', ), ), ], 'icon_style' => [ 'checkout_proceed_icon' => array( 'type' => 'icon', 'label' => __('Icon'), 'default' => '', ), 'icon_position' => array( 'type' => 'radio', 'label' => __('Alignment'), 'default' => '', 'list' => array( 'kkart-checkout-icon-left' => __('Left'), '' => __('Right') ), 'addClass' => ['{{element}} .kkart-checkout-proceed' => '{{val}}'], 'req' => array( '!checkout_proceed_icon' => 'none' ), ), 'icon_spacing' => array( 'type' => 'slider', 'label' => __('Icon Spacing'), 'min' => 1, 'step' => 1, 'max' => 100, 'default' => 5, 'screen' => 1, 'css' => ['{{element}} .kkart-checkout-proceed-icon' => 'padding: 0 {{val}}px;'], 'req' => array( '!checkout_proceed_icon' => 'none' ), ), ], 'styles' => array( 'btn_style' => __('Button Styles'), 'border_style' => __('Border Style'), 'icon_style' => __('Icon Style') ), ) ); // Checkout form holder pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_checkout_form', array( 'name' => __('Checkout form Holder'), 'group' => 'kkart Checkout', 'func' => 'kkart_sc_checkout_form', 'html' => '
{{checkout_form}}
', 'params' => array( 'tab_colors' => array( 'type' => 'radio', 'label' => __('Tab Colors'), 'list' => array( '' => __('Normal'), 'active' => __('Active'), ), ), 'active_tab_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'default' => '#000000', 'css' => [ '{{element}} .kkart-checkout-active-tab .kkart-checkout-tab-header' => 'background-color:{{val}}!important'], 'show' => ['tab_colors' => 'active'] ), 'active_tab_text' =>array( 'label' => __('Color'), 'type' => 'color', 'default' => '#FFFFFF', 'css' => ['{{element}} .kkart-checkout-active-tab .kkart-checkout-tab-header' => 'color:{{val}}!important'], 'show' => ['tab_colors' => 'active'] ), 'inactive_tab' =>array( 'label' => __('Background Color'), 'type' => 'color', 'default' => '#cccccc', 'css' => ['{{element}} .kkart-checkout-tab-header' => 'background-color:{{val}}'], 'show' => ['tab_colors' => ''] ), 'inactive_tab_text' =>array( 'label' => __('Color'), 'type' => 'color', 'default' => '#000000', 'css' => ['{{element}} .kkart-checkout-tab-header' => 'color:{{val}}'], 'show' => ['tab_colors' => ''] ), 'tab_spacing' =>array( 'type' => 'spinner', 'label' => __('Spacing'), 'screen' => 1, 'css' => ['{{element}} .kkart-checkout-holder > div:not(:last-child)' => 'margin-bottom:{{val}}px'], 'show' => ['tab_colors' => ''] ) ), 'proceed_button'=> array( 'proceed_colors' => array( 'type' => 'radio', 'label' => __('Button Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'proceed_button_bg_color'=> array( 'label' => __('Background Color'), 'type' => 'color', 'css' => ['{{element}} .checkout-tabs-proceed' => 'background-color:{{val}}'], 'show' => ['proceed_colors' => ''] ), 'proceed_button_text_color'=> array( 'label' => __('Color'), 'type' => 'color', 'css' => ['{{element}} .checkout-tabs-proceed' => 'color:{{val}}'], 'show' => ['proceed_colors' => ''] ), 'proceed_button_hover_bg'=> array( 'label' => __('Background Color'), 'type' => 'color', 'css' => ['{{element}} .checkout-tabs-proceed:hover' => 'background-color:{{val}}'], 'show' => ['proceed_colors' => 'hover'] ), 'proceed_button_hover_color'=> array( 'label' => __('Color'), 'type' => 'color', 'css' => ['{{element}} .checkout-tabs-proceed:hover' => 'color:{{val}}'], 'show' => ['proceed_colors' => 'hover'] ), 'proceed_button_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .checkout-tabs-proceed' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'proceed_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!proceed_button_border_type' => ''] ), 'proceed_button_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .checkout-tabs-proceed' => 'border-color: {{val}};'], 'req' => ['!proceed_button_border_type' => ''], 'show' => ['proceed_border_colors' => ''] ), 'proceed_button_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .checkout-tabs-proceed:hover' => 'border-color: {{val}};'], 'req' => ['!proceed_button_border_type' => ''], 'show' => ['proceed_border_colors' => 'hover'] ), 'proceed_button_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .checkout-tabs-proceed' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!proceed_button_border_type' => ''] ), 'proceed_button_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .checkout-tabs-proceed' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'proceed_button_button_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .checkout-tabs-proceed' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), ), 'edit_button'=> array( 'edit_colors' => array( 'type' => 'radio', 'label' => __('Edit Button Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'edit_button_bg_color'=> array( 'label' => __('Background Color'), 'type' => 'color', 'css' => ['{{element}} .checkout_edit_button' => 'background-color:{{val}}'], 'show' => ['edit_colors' => ''] ), 'edit_button_color'=> array( 'label' => __('Color'), 'type' => 'color', 'css' => ['{{element}} .checkout_edit_button' => 'color:{{val}}'], 'show' => ['edit_colors' => ''] ), 'edit_button_hover_bg'=> array( 'label' => __('Background Color'), 'type' => 'color', 'css' => ['{{element}} .checkout_edit_button:hover' => 'background-color:{{val}}'], 'show' => ['edit_colors' => 'hover'] ), 'edit_button_hover_color'=> array( 'label' => __('Color'), 'type' => 'color', 'css' => ['{{element}} .checkout_edit_button:hover' => 'color:{{val}}'], 'show' => ['edit_colors' => 'hover'] ), 'edit_button_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .checkout_edit_button' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'edit_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!edit_button_border_type' => ''] ), 'edit_button_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .checkout_edit_button' => 'border-color: {{val}};'], 'req' => ['!edit_button_border_type' => ''], 'show' => ['edit_border_colors' => ''] ), 'edit_button_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .checkout_edit_button:hover' => 'border-color: {{val}};'], 'req' => ['!edit_button_border_type' => ''], 'show' => ['edit_border_colors' => 'hover'] ), 'edit_button_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .checkout_edit_button' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!edit_button_border_type' => ''] ), 'edit_button_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .checkout_edit_button' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'edit_button_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .checkout_edit_button' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), ), 'billing_here_button' => array( 'billing_here_colors' => array( 'type' => 'radio', 'label' => __('Billing Here Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'billing_here' => array( 'type' => 'text', 'label' => __('Billing Here Button'), 'default' => 'Use This', 'addAttr' => ['{{element}} .kkart-addresses-holder' => 'data-here-text="{{billing_here}}"'], 'req' => ['form_type' => ''] ), 'here_btn_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-billing-here' => 'background-color:{{val}}'], 'show' => ['billing_here_colors'=> ''] ), 'btn_text_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-billing-here' => 'color:{{val}}'], 'show' => ['billing_here_colors' => ''] ), 'btn_hover_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-billing-here:hover' => 'background-color:{{val}}'], 'show' => ['billing_here_colors'=> 'hover'] ), 'billing_hover_text_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-billing-here:hover' => 'color:{{val}}'], 'show' => ['billing_here_colors'=> 'hover'] ), 'billing_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-billing-here' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'billing_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!billing_border_type' => ''], ), 'billing_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-billing-here' => 'border-color: {{val}};'], 'req' => ['!billing_border_type' => ''], 'show' => ['billing_border_colors' => ''] ), 'billing_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .kkart-billing-here:hover' => 'border-color: {{val}};'], 'req' => ['!billing_border_type' => ''], 'show' => ['billing_border_colors' => 'hover'] ), 'billing_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-here' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!billing_border_type' => ''] ), 'btn_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-here' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'btn_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-here' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'here_btn_display' => array( 'type' => 'select', 'label' => __('Display'), 'screen' => 1, 'default' => '', 'css' => ['{{element}} .kkart-billing-here' => 'display:{{val}}'], 'list' => array( '' => __('Full'), 'inline-block' => __('Inline'), ), ), 'here_btn_width' => array( 'type' => 'slider', 'label' => __('Width'), 'min' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-billing-here' => 'width:{{val}}%'], ), ), 'billing_edit_button' => array( 'billing_edit' => array( 'type' => 'text', 'label' => __('Billing Edit'), 'default' => 'Edit', 'addAttr' => ['{{element}} .kkart-addresses-holder' => 'data-edit-text="{{billing_edit}}"'], ), 'billing_edit_colors' => array( 'type' => 'radio', 'label' => __('Billing Edit Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'edit_btn_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-billing-edit' => 'background-color:{{val}}'], 'show' => ['billing_edit_colors' => ''] ), 'edit_btn_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-billing-edit' => 'color:{{val}}'], 'show' => ['billing_edit_colors' => ''] ), 'edit_btn_hover_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-billing-edit:hover' => 'background-color:{{val}}'], 'show' => ['billing_edit_colors' => 'hover'] ), 'edit_btn_hover_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-billing-edit:hover' => 'color:{{val}}'], 'show' => ['billing_edit_colors' => 'hover'] ), 'edit_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-billing-edit' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'edit_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!edit_border_type' => ''] ), 'edit_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-billing-edit' => 'border-color: {{val}};'], 'req' => ['!edit_border_type' => ''], 'show' => ['edit_border_colors' => ''] ), 'edit_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .kkart-billing-edit:hover' => 'border-color: {{val}};'], 'req' => ['!edit_border_type' => ''], 'show' => ['edit_border_colors' => 'hover'] ), 'edit_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-edit' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!edit_border_type' => ''], ), 'edit_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-edit' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'edit_btn_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-edit' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'edit_btn_display' => array( 'type' => 'select', 'label' => __('Display'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-edit' => 'display:{{val}}'], 'list' => array( '' => __('Full'), 'inline-block' => __('Inline'), ), ), 'edit_btn_width' => array( 'type' => 'slider', 'label' => __('Width'), 'min' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-billing-edit' => 'width:{{val}}%'], ), ), 'delete_button' => array( 'billing_delete_colors' => array( 'type' => 'radio', 'label' => __('Billing Delete Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'billing_delete' => array( 'type' => 'text', 'label' => __('Billing Delete'), 'default' => 'Delete', 'addAttr' => ['{{element}} .kkart-addresses-holder' => 'data-delete-text="{{billing_delete}}"'], ), 'del_btn_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-billing-delete' => 'background-color:{{val}}'], 'show' => ['billing_delete_colors' => ''] ), 'del_btn_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-billing-delete' => 'color:{{val}}'], 'show' => ['billing_delete_colors' => ''] ), 'del_btn_hover_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-billing-delete:hover' => 'background-color:{{val}}'], 'show' => ['billing_delete_colors' => 'hover'] ), 'del_btn_hover_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-billing-delete:hover' => 'color:{{val}}'], 'show' => ['billing_delete_colors' => 'hover'] ), 'del_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-billing-delete' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'del_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!del_border_type' => ''] ), 'del_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-billing-delete' => 'border-color: {{val}};'], 'req' => ['!del_border_type' => ''], 'show' => ['del_border_colors' => ''] ), 'del_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .kkart-billing-delete:hover' => 'border-color: {{val}};'], 'req' => ['!del_border_type' => ''], 'show' => ['del_border_colors' => 'hover'] ), 'del_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-delete' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!del_border_type' => ''] ), 'del_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-delete' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'del_btn_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-delete' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'del_btn_display' => array( 'type' => 'select', 'label' => __('Display'), 'screen' => 1, 'css' => ['{{element}} .kkart-billing-delete' => 'display:{{val}}'], 'list' => array( '' => __('Full'), 'inline-block' => __('Inline'), ), ), 'del_btn_width' => array( 'type' => 'slider', 'label' => __('Width'), 'min' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-billing-delete' => 'width:{{val}}%'], ), ), 'add_address' => array( 'add_addre_text' => array( 'type' => 'text', 'label' => __('Add Address Text'), 'default' => '+ Add New Address', ), 'add_addre_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-address-form-headding' => 'color:{{val}}' ] ), 'add_font_weight' => array( 'type' => 'select', 'label' => __('Font Weight'), 'default' => 'normal', 'list' => array( 'normal' => __('Normal'), 'bold' => __('Bold'), 'bolder' => __('Bolder'), 'lighter' => __('Lighter') ), 'css' => [ '{{element}} .kkart-address-form-headding' => 'font-weight:{{val}}' ] ) ), 'form_save_button' => array( 'billing_save_colors' => array( 'type' => 'radio', 'label' => __('Billing Save Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'save_addre_text' => array( 'type' => 'text', 'label' => __('Save Address Text'), 'default' => 'Save', ), 'save_btn_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-save-address-form' => 'background-color:{{val}}'], 'show' => ['billing_save_colors' => ''] ), 'save_btn_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-save-address-form' => 'color:{{val}}'], 'show' => ['billing_save_colors' => ''] ), 'save_btn_hover_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-save-address-form:hover' => 'background-color:{{val}}'], 'show' => ['billing_save_colors' => 'hover'] ), 'save_btn_hover_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-save-address-form:hover' => 'color:{{val}}'], 'show' => ['billing_save_colors' => 'hover'] ), 'save_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-save-address-form' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'billing_save_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!save_border_type' => ''] ), 'billing_savebt_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-save-address-form' => 'border-color: {{val}};'], 'req' => ['!save_border_type' => ''], 'show' => ['billing_save_border_colors' => ''] ), 'billing_savebt_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .kkart-save-address-form:hover' => 'border-color: {{val}};'], 'req' => ['!save_border_type' => ''], 'show' => ['billing_save_border_colors' => 'hover'] ), 'billing_savebt_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-save-address-form' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!save_border_type' => ''] ), 'save_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-save-address-form' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'save_btn_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-save-address-form' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'save_btn_display' => array( 'type' => 'select', 'label' => __('Display'), 'screen' => 1, 'default' => '', 'css' => ['{{element}} .kkart-save-address-form' => 'display:{{val}}'], 'list' => array( '' => __('Full'), 'inline-block' => __('Inline'), ), ), 'save_btn_width' => array( 'type' => 'slider', 'label' => __('Width'), 'min' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-save-address-form' => 'width:{{val}}%'], ), ), 'form_cancel_button' => array( 'billing_cancel_colors' => array( 'type' => 'radio', 'label' => __('Billing Cancel Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), ), 'cancel_addre_text' => array( 'type' => 'text', 'label' => __('Cancel Address Text'), 'default' => 'Cancel', ), 'cancel_btn_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-cancel-address-form' => 'background-color:{{val}}'], 'show' => ['billing_cancel_colors' => ''] ), 'cancel_btn_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-cancel-address-form' => 'color:{{val}}'], 'show' => ['billing_cancel_colors' => ''] ), 'cancel_btn_hover_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-cancel-address-form:hover' => 'background-color:{{val}}'], 'show' => ['billing_cancel_colors' => 'hover'] ), 'cancel_button_hover_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-cancel-address-form:hover' => 'color:{{val}}'], 'show' => ['billing_cancel_colors' => 'hover'] ), 'cancel_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-cancel-address-form' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'billing_cancel_border_colors' => array( 'type' => 'radio', 'label' => __('Border Colors'), 'list' => array( '' => __('Normal Color'), 'hover' => __('Hover Color'), ), 'req' => ['!cancel_border_type' => ''] ), 'billing_cancelbt_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-cancel-address-form' => 'border-color: {{val}};'], 'req' => ['!cancel_border_type' => ''], 'show' => ['billing_cancel_border_colors' => ''] ), 'billing_cancelbt_border_hover' => array( 'type' => 'color', 'label' => __('Border Hover'), 'css' => ['{{element}} .kkart-cancel-address-form:hover' => 'border-color: {{val}};'], 'req' => ['!cancel_border_type' => ''], 'show' => ['billing_cancel_border_colors' => 'hover'] ), 'billing_cancelbt_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-cancel-address-form' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!cancel_border_type' => ''] ), 'billing_cancelbt_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-cancel-address-form' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], ), 'cancel_btn_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-cancel-address-form' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'cancel_btn_display' => array( 'type' => 'select', 'label' => __('Display'), 'screen' => 1, 'default' => '', 'css' => ['{{element}} .kkart-cancel-address-form' => 'display:{{val}}'], 'list' => array( '' => __('Full'), 'inline-block' => __('Inline'), ), ), 'cancel_btn_width' => array( 'type' => 'slider', 'label' => __('Width'), 'min' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-cancel-address-form' => 'width:{{val}}%'], ), ), 'address_block' => array( 'address_block_colors' => array( 'type' => 'radio', 'label' => __('Address Block Color'), 'list' => array( '' => __('Normal'), 'active' => __('Active') ) ), 'address_block_color' =>array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-address-details' => 'color:{{val}}'], 'show' => [ 'address_block_colors' => ''] ), 'address_block_bgcolor' =>array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-address-details' => 'background-color:{{val}}'], 'show' => [ 'address_block_colors' => ''] ), 'active_block_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} .kkart-active-address-details' => 'color:{{val}}'], 'show' => [ 'address_block_colors' => 'active'] ), 'active_block_bgcolor' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-active-address-details' => 'background-color:{{val}}'], 'show' => [ 'address_block_colors' => 'active'] ) ), 'styles' => array( 'proceed_button' => __('Proceed Button'), 'edit_button' => __('Edit Button'), 'billing_here_button' => __('Billing Here Button'), 'billing_edit_button' => __('Billing Edit Button'), 'delete_button' => __('Billing Delete Button'), 'add_address' => __('Add Address Text'), 'form_save_button' => __('Save Button'), 'form_cancel_button' => __('Cancel Button'), 'address_block' => __('Address Block') ) ) ); // Order information pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_order_info',array( 'name' => __('Order Info'), 'group' => 'kkart received', 'func' => 'kkart_sc_order_info', 'html' => '
{{failed_text}}
{{info_text}}
{{order_not_found_txt}}
', 'params' => array( 'editor_view' => array( 'type' => 'select', 'label' => __('Order views on editor'), 'list' => array( '' => __('Order info'), 'failed' => __('Order failed'), 'not_found' => __('Order not Found'), ), ), 'info_text' => array( 'type' => 'textarea', 'label' => __('Order Success Text'), 'default' => '

Thank you. Your order has been received.

Order number : $order_number

Date : $order_date

Email : $billing_email

Total : $order_total

Payment method : $payment_method

', 'desc' => 'You can use the varibles - $order_number, $order_date, $billing_email, $order_total, $payment_method. and also you can use [if] attribute like(if="$payment_method") to skip empty variable holders', ), 'align' => array( 'type' => 'radio', 'label' => __('alignment'), 'default' => 'left', 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), 'css' => ['{{element}} .kkart-order-info-holder' => 'text-align:{{val}}'] ), 'color' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} .kkart-order-info-holder *' => 'color:{{val}}'] ), 'typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-order-info-holder' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), ), 'order_failed' => array( 'failed_text' => array( 'type' => 'textarea', 'label' => __('Order Failed Text'), 'default' => '

Unfortunately your order cannot be processed as the originating bank/merchant has declined your transaction. Please attempt your purchase again.

', ), 'failed_color' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} .kkart-order-info-holder .kkart-order-failed-holder *' => 'color:{{val}}'] ), 'failed_typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-order-info-holder .kkart-order-failed-holder' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), 'failed_btns' => array( 'type' => 'radio', 'label' => __('buttons'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'failed_btn_color' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} .kkart-order-failed-holder .button' => 'color:{{val}}'], 'show' => ['failed_btns' => ''] ), 'failed_btn_bgcolor' => array( 'type' => 'color', 'label' => __('bgcolor'), 'css' => ['{{element}} .kkart-order-failed-holder .button' => 'background-color:{{val}}'], 'show' => ['failed_btns' => ''] ), 'failed_btn_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-order-failed-holder .button' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], 'show' => ['failed_btns' => ''] ), 'failed_btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-order-failed-holder .button' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['failed_btns' => ''] ), 'failed_btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-order-failed-holder .button' => 'border-color: {{val}};'], 'req' => ['!failed_btn_border_type' => ''], 'show' => ['failed_btns' => ''] ), 'failed_btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-order-failed-holder .button' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!failed_btn_border_type' => ''], 'show' => ['failed_btns' => ''] ), 'failed_btn_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-order-failed-holder .button' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!failed_btn_border_type' => ''], 'show' => ['failed_btns' => ''] ), 'failed_btn_color_hover' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} .kkart-order-failed-holder .button:hover' => 'color:{{val}}'], 'show' => ['failed_btns' => 'hover'] ), 'failed_btn_bgcolor_hover' => array( 'type' => 'color', 'label' => __('bgcolor'), 'css' => ['{{element}} .kkart-order-failed-holder .button:hover' => 'background-color:{{val}}'], 'show' => ['failed_btns' => 'hover'] ), 'failed_btn_typo_hover' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-order-failed-holder .button:hover' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], 'show' => ['failed_btns' => 'hover'] ), 'failed_btn_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-order-failed-holder .button:hover' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['failed_btns' => 'hover'] ), 'failed_btn_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-order-failed-holder .button:hover' => 'border-color: {{val}};'], 'req' => ['!failed_btn_border_type_hover' => ''], 'show' => ['failed_btns' => 'hover'] ), 'failed_btn_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-order-failed-holder .button:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!failed_btn_border_type_hover' => ''], 'show' => ['failed_btns' => 'hover'] ), 'failed_btn_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-order-failed-holder .button:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!failed_btn_border_type_hover' => ''], 'show' => ['failed_btns' => 'hover'] ), 'failed_btn_padding' => array( 'type' => 'padding', 'label' => __('Button Padding'), 'screen' => 1, 'css' => ['{{element}} .kkart-order-failed-holder .button' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), 'failed_btn_space' => array( 'type' => 'spinner', 'label' => __('Button Spacing'), 'screen' => 1, 'css' => ['{{element}} .kkart-order-failed-holder .button:first-child' => 'margin-right:{{val}}px'], ), ), 'order_not_found' => array( 'order_not_found_txt' => array( 'type' => 'textarea', 'label' => __('Order Not Found'), 'default' => 'Unfortunately your order is not found. Please attempt your purchase again.', ), 'not_found_color' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} .kkart-order-info-holder .kkart-order-not-found-holder *' => 'color:{{val}}'] ), 'not_found_typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-order-info-holder .kkart-order-not-found-holder' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), ), 'styles' => array( 'order_failed' => __('Order failed'), 'order_not_found' => __('Order not found'), ), ) ); // Order Details pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_order_details',array( 'name' => __('Order Details'), 'group' => 'kkart received', 'func' => 'kkart_sc_order_details', 'html' => '
{{download_title}}
{{download_details}}
{{order_title}}
{{order_details}}
', 'params' => array( 'order_title' => array( 'type' => 'text', 'label' => __('Order Title'), 'default' => '

Order details

', ), 'order_title_color' => array( 'type' => 'color', 'label' => __('Order color'), 'css' => ['{{element}} .kkart-order-details-title' => 'color:{{val}}'] ), 'order_title_typography' => array( 'type' => 'typography', 'label' => __('Order typography'), 'css' => [ '{{element}} .kkart-order-details-title' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), 'download_title' => array( 'type' => 'text', 'label' => __('Download Title'), 'default' => '

Downloads

', ), 'download_title_color' => array( 'type' => 'color', 'label' => __('Download color'), 'css' => ['{{element}} .kkart-order-details-title' => 'color:{{val}}'] ), 'download_title_typography' => array( 'type' => 'typography', 'label' => __('Download typography'), 'css' => [ '{{element}} .kkart-order-details-title' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), ), ) ); // Order Address pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_order_address',array( 'name' => __('Order Address'), 'group' => 'kkart received', 'func' => 'kkart_sc_order_address', 'html' => '
{{billing_title}}
{{billing_details}}
{{shipping_title}}
{{shipping_details}}
', 'params' => array( 'billing_title' => array( 'type' => 'text', 'label' => __('Billing Title'), 'default' => '

Billing Address

', ), 'shipping_title' => array( 'type' => 'text', 'label' => __('Shipping Title'), 'default' => '

Shipping Address

', ) ), ) ); // Order pay pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_order_pay',array( 'name' => __('Order Pay'), 'group' => 'kkart Checkout', 'icon' => 'fas fa-money-bill-alt', 'func' => 'kkart_sc_order_pay', 'html' => '
{{messages}}
{{order_pay_form}}
{{order_pay_details}}
', 'params' => array( 'pay_color' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} .kkart-order-pay-holder *' => 'color:{{val}}'] ), 'pay_typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-order-pay-holder' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ] ), ), 'button_style' => array( 'pay_btns' => array( 'type' => 'radio', 'label' => __('buttons'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'pay_btn_color' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} #place_order' => 'color:{{val}}'], 'show' => ['pay_btns' => ''] ), 'pay_btn_bgcolor' => array( 'type' => 'color', 'label' => __('bgcolor'), 'css' => ['{{element}} #place_order' => 'background-color:{{val}}'], 'show' => ['pay_btns' => ''] ), 'pay_btn_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} #place_order' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], 'show' => ['pay_btns' => ''] ), 'pay_btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} #place_order' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['pay_btns' => ''] ), 'pay_btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} #place_order' => 'border-color: {{val}};'], 'req' => ['!pay_btn_border_type' => ''], 'show' => ['pay_btns' => ''] ), 'pay_btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} #place_order' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!pay_btn_border_type' => ''], 'show' => ['pay_btns' => ''] ), 'pay_btn_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} #place_order' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!pay_btn_border_type' => ''], 'show' => ['pay_btns' => ''] ), 'pay_btn_color_hover' => array( 'type' => 'color', 'label' => __('color'), 'css' => ['{{element}} #place_order:hover' => 'color:{{val}}'], 'show' => ['pay_btns' => 'hover'] ), 'pay_btn_bgcolor_hover' => array( 'type' => 'color', 'label' => __('bgcolor'), 'css' => ['{{element}} #place_order:hover' => 'background-color:{{val}}'], 'show' => ['pay_btns' => 'hover'] ), 'pay_btn_typo_hover' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} #place_order:hover' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', ], 'show' => ['pay_btns' => 'hover'] ), 'pay_btn_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} #place_order:hover' => 'border-style: {{val}};' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => ['pay_btns' => 'hover'] ), 'pay_btn_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} #place_order:hover' => 'border-color: {{val}};'], 'req' => ['!pay_btn_border_type_hover' => ''], 'show' => ['pay_btns' => 'hover'] ), 'pay_btn_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} #place_order:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!pay_btn_border_type_hover' => ''], 'show' => ['pay_btns' => 'hover'] ), 'pay_btn_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} #place_order:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!pay_btn_border_type_hover' => ''], 'show' => ['pay_btns' => 'hover'] ), 'pay_btn_padding' => array( 'type' => 'padding', 'label' => __('Button Padding'), 'screen' => 1, 'css' => ['{{element}} #place_order' => 'padding-top: {{val[0]}}px; padding-right: {{val[1]}}px; padding-bottom: {{val[2]}}px; padding-left: {{val[3]}}px'], ), ), 'styles' => array( 'button_style' => __('Button Style'), ) ) ); /////////////////////////////////// // Widget copied from pagelayer /////////////////////////////////// // Product Rating pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_product_rating', array( 'name' => __('Product Rating'), 'group' => 'kkart', 'use_inside' => ['pl_kkart_archive_item'], 'html' => '
', 'params' => array( 'show_rating' => array( 'type' => 'checkbox', 'label' => __('Show Rating'), 'default' => 'true', ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'css' => ['{{element}} .kkart-product-rating' => 'width:100%;text-align: {{val}}'], 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), ), 'star_color' => array( 'type' => 'color', 'label' => __('Star Color'), 'css' => ['{{element}} .pagelayer-stars-icon:before' => 'color: {{val}}'], 'req' => ['!show_rating' => ''], ), 'star_emp_color' => array( 'type' => 'color', 'label' => __('Empty Star Color'), 'css' => ['{{element}} .pagelayer-stars-container' => 'color: {{val}}'], 'req' => ['!show_rating' => ''], ), 'star_size' => array( 'type' => 'slider', 'label' => __('Star Size'), 'units' => [ 'px', 'em' ], 'step' => 0.1, 'css' => ['{{element}} .pagelayer-stars-container' => 'font-size:{{val}}'], 'req' => ['!show_rating' => ''], ), 'space_between_stars' => array( 'type' => 'slider', 'label' => __('Space Between Stars'), 'units' => [ 'px', 'em' ], 'step' => 0.1, 'css' => ['{{element}} .pagelayer-stars-icon' => 'letter-spacing: {{val}}'], 'req' => ['!show_rating' => ''], ), ), 'review_count_style' => array( 'show_review_count' => array( 'type' => 'checkbox', 'label' => __('Show Review Count'), 'default' => 'true', ), 'count_text' => array( 'type' => 'text', 'label' => __('Count Text'), 'np' => 1, 'default' => 'customer review', 'edit' => '.kkart-count-text', 'req' => ['!show_review_count' => ''], ), 'review_link_color' => array( 'type' => 'color', 'label' => __('Link Color'), 'css' => ['{{element}} .kkart-review-link' => 'color: {{val}}'], 'req' => ['!show_review_count' => ''], ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-review-link' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], 'req' => ['!show_review_count' => ''], ), 'show_review_brackets' => array( 'type' => 'checkbox', 'label' => __('Show Review Brackets'), 'default' => 'true', ), 'space_between' => array( 'type' => 'slider', 'label' => __('Space Between'), 'units' => [ 'px', 'em' ], 'step' => 1, 'css' => ['{{element}} .kkart-review-link' => 'margin-left : {{val}}'], 'req' => ['!show_review_count' => ''], ), ), 'styles' =>[ 'review_count_style' => __('Review Count Style'), ], ) ); // Product Meta pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_meta', array( 'name' => __('Product meta'), 'icon' => 'fa fa-info', 'group' => 'kkart', 'edit_props' => ['.sku_value' => '_sku'], 'html' => '
{{sku_label}}: {{sku_value}} {{category_label}}{{category_value}} {{tag_label}}{{tag_value}}
', 'params' => array( 'sku_label' => array( 'type' => 'text', 'label' => __('SKU label'), 'default' => 'SKU', 'edit' => '.sku_label', ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'css' => ['{{element}} .kkart-product-meta' => 'text-align: {{val}}'], 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), ), 'display' => array( 'type' => 'radio', 'label' => __('Display'), 'css' => ['{{element}} .kkart-product-meta > span' => 'display: {{val}}'], 'list' => array( 'inline-block' => __('Inline Block'), 'block' => __('Block'), ), ), 'space_between' => array( 'type' => 'slider', 'label' => __('Space Between'), 'step' => 0.1, 'css' => [ '{{element}} .kkart-product-meta:not(.kkart-meta-block) > span:not(:first-child)' => 'margin-left: {{val}}px', '{{element}} .kkart-product-meta.kkart-meta-block > span:not(:last-child)' => 'margin-bottom: {{val}}px', ], ), 'meta_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-product-meta span' => 'color: {{val}}'], ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-product-meta span' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'link_color' => array( 'type' => 'color', 'label' => __('Link Color'), 'css' => ['{{element}} .kkart-product-meta a' => 'color: {{val}}'], ), 'linl_typo' => array( 'type' => 'typography', 'label' => __('Link typography'), 'css' => ['{{element}} .kkart-product-meta a' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), ), ) ); // Product short description pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_short_desc', array( 'name' => __('Product Short Description'), 'icon' => 'far fa-file-alt', 'group' => 'kkart', 'edit_props' => ['.kkart-short-desc' => 'post_excerpt'], 'html' => '
{{product_short_desc}}
', 'params' => array( 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'css' => ['{{element}} .kkart-short-desc' => 'text-align: {{val}}'], 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), ), 'meta_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-short-desc' => 'color: {{val}}'], ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-short-desc' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), ), ) ); // Products style $products_style = array( 'column_gap' => array( 'type' => 'slider', 'label' => __('Column Gap'), 'units' => ['px', '%'], 'screen' => 1, 'default' => 20, 'step' => 0.2, 'max' => 100, 'css' => ['{{element}} ul.products li.product' => 'margin-right: {{val}}'], ), 'row_gap' => array( 'type' => 'slider', 'label' => __('Row Gap'), 'units' => ['px', '%'], 'screen' => 1, 'default' => 20, 'step' => 0.2, 'max' => 100, 'css' => ['{{element}} ul.products li.product' => 'margin-bottom: {{val}}'], ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), 'addAttr' => ['{{element}} .pagelayer-product-related-container' => 'pagelayer-content-align="{{align}}"'], 'css' => ['{{element}} ul.products li.product' => 'text-align:{{val}}'], ), 'img_lable' => array( 'type' => 'heading', 'label' => __('Image'), ), 'img_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .attachment-kkart_thumbnail' => 'border-style: {{val}}', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'img_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .attachment-kkart_thumbnail' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px' ], 'req' => [ '!img_border_type' => '' ], ), 'img_border_color_hover' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .attachment-kkart_thumbnail' => 'border-color: {{val}}'], 'show' => ['img_border_type' => ''], ), 'img_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} .attachment-kkart_thumbnail' => 'border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}; -webkit-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};-moz-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};', ], ), 'img_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} .attachment-kkart_thumbnail' => 'margin-bottom: {{val}}'], ), 'title_lable' => array( 'type' => 'heading', 'label' => __('Title'), ), 'title_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} ul.products li.product .kkart-loop-product__title' => 'color: {{val}}', '{{element}} ul.products li.product .kkart-loop-category__title' => 'color: {{val}}' ], ), 'title_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} ul.products li.product .kkart-loop-product__title' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', '{{element}} ul.products li.product .kkart-loop-category__title' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'title_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => [ '{{element}} ul.products li.product .kkart-loop-product__title' => 'margin-bottom: {{val}}', '{{element}} ul.products li.product .kkart-loop-category__title' => 'margin-bottom: {{val}}' ], ), 'rating_lable' => array( 'type' => 'heading', 'label' => __('Stars Rating'), ), 'star_color' => array( 'type' => 'color', 'label' => __('Star Color'), 'css' => ['{{element}} ul.products li.product .star-rating' => 'color: {{val}}'], ), 'empty_star_color' => array( 'type' => 'color', 'label' => __('Empty Star Color'), 'css' => ['{{element}} ul.products li.product .star-rating::before' => 'color: {{val}}'], ), 'star_size' => array( 'type' => 'slider', 'label' => __('Star Size'), 'max' => 5, 'step' => 0.1, 'css' => ['{{element}} ul.products li.product .star-rating' => 'font-size: {{val}}em'], ), 'star_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} ul.products li.product .star-rating' => 'margin-bottom: {{val}}'], ), 'price_lable' => array( 'type' => 'heading', 'label' => __('Price Style'), ), 'price_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} ul.products li.product .price' => 'color: {{val}}', '{{element}} ul.products li.product .price ins' => 'color: {{val}}', '{{element}} ul.products li.product .price ins .amount' => 'color: {{val}}', ], ), 'price_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} ul.products li.product .price' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'reg_price_lable' => array( 'type' => 'heading', 'label' => __('Regular Price'), ), 'reg_price_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} ul.products li.product .price del .amount' => 'color:{{val}}', '{{element}} ul.products li.product .price del' => 'color:{{val}}' ] ), 'reg_price_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} ul.products li.product .price del .amount' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;', '{{element}} ul.products li.product .price del' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'button_lable' => array( 'type' => 'heading', 'label' => __('Button'), ), 'button_colors'=> array( 'type' => 'radio', 'label' => '', 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), ), 'btn_color'=> array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} ul.products li.product .button' => 'color:{{val}}'], 'show' => [ 'button_colors' => '' ], ), 'btn_bg_color'=> array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} ul.products li.product .button' => 'background-color:{{val}}'], 'show' => [ 'button_colors' => '' ], ), 'btn_border_color'=> array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} ul.products li.product .button' => 'border-color:{{val}}'], 'show' => [ 'button_colors' => '' ], ), 'btn_hover_color'=> array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} ul.products li.product .button:hover' => 'color:{{val}}'], 'show' => [ 'button_colors' => 'hover' ], ), 'btn_bg_hover_color'=> array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} ul.products li.product .button:hover' => 'background-color:{{val}}'], 'show' => [ 'button_colors' => 'hover' ], ), 'btn_border_hover_color'=> array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} ul.products li.product .button:hover' => 'border-color:{{val}}'], 'show' => [ 'button_colors' => 'hover' ], ), 'btnb_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} ul.products li.product .button' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} ul.products li.product .button' => 'border-style: {{val}}', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} ul.products li.product .button' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px', ], 'req' => [ '!btn_border_type' => '' ], ), 'btn_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} ul.products li.product .button' => 'border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}; -webkit-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};-moz-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};', ], ), 'btn_text_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} ul.products li.product .button' => 'padding: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}; -webkit-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};-moz-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};', ], ), 'btn_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} ul.products li.product .button' => 'margin-top:{{val}}'], ), 'view_cart_lable' => array( 'type' => 'heading', 'label' => __('View Cart'), ), 'view_cart_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-view-btn' => 'color: {{val}}'], ), 'view_cart_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-view-btn' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), ); // Products heading style $products_heading = array( 'heading_show'=> array( 'type' => 'checkbox', 'label' => __('Heading Style'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-product-related-container' => 'pagelayer-heading-show="{{heading_show}}"'], ), 'heading_color'=> array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .products > h2' => 'color: {{val}}'], 'req' => ['heading_show' => 'true'], ), 'heading_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .products > h2' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], 'req' => ['heading_show' => 'true'], ), 'heading_align'=> array( 'type' => 'radio', 'label' => __('Alignment'), 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), 'css' => ['{{element}} .products > h2' => 'text-align: {{val}}'], 'req' => ['heading_show' => 'true'], ), 'heading_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} .products > h2' => 'margin-bottom: {{val}}'], 'req' => ['heading_show' => 'true'], ), ); // Products box style $products_box = array( 'box_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} ul.products li.product' => 'border-style: {{val}}', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'box_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} ul.products li.product' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px', ], 'req' => [ '!box_border_type' => '' ], ), 'box_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} ul.products li.product' => 'border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}; -webkit-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};-moz-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};', ], ), 'box_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} ul.products li.product' => 'border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}; -webkit-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};-moz-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};', ], ), 'box_colors' => array( 'type' => 'radio', 'label' => '', 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), ), 'box_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} ul.products li.product' => 'background-color: {{val}}'], 'show' => ['box_colors' => ''], ), 'box_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} ul.products li.product' => 'border-color: {{val}}'], 'show' => ['box_colors' => ''], ), 'box_shadow' => [ 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} ul.products li.product' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}} !important;'], 'show' => ['box_colors' => ''], ], 'box_bg_hover_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} ul.products li.product:hover' => 'background-color: {{val}}'], 'show' => ['box_colors' => 'hover'], ), 'box_border_hover_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} ul.products li.product:hover' => 'border-color: {{val}}'], 'show' => ['box_colors' => 'hover'], ), 'box_hover_shadow' => [ 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} ul.products li.product:hover' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}} !important;'], 'show' => ['box_colors' => 'hover'], ], ); // Products sale flash style $products_sale_flash = array( 'sale_flash' => array( 'type' => 'checkbox', 'label' => __('Sale Flash'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-product-related-container' => 'pagelayer-sale-flash="{{sale_flash}}"'], ), 'flash_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} ul.products li.product span.onsale' => 'color: {{val}}'], 'req' => [ 'sale_flash' => 'true'], ), 'flash_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} ul.products li.product span.onsale' => 'background-color: {{val}}'], 'req' => [ 'sale_flash' => 'true'], ), 'flash_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} ul.products li.product span.onsale' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], 'req' => [ 'sale_flash' => 'true'], ), 'flash_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} .ul.products li.product span.onsale' => 'border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}; -webkit-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};-moz-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};', ], 'req' => [ 'sale_flash' => 'true'], ), 'flash_width' => array( 'type' => 'slider', 'label' => __('Width'), 'units' => [ 'px', '%' ], 'css' => ['{{element}} ul.products li.product span.onsale' => 'min-width: {{val}};'], 'req' => [ 'sale_flash' => 'true'], ), 'flash_height' => array( 'type' => 'slider', 'label' => __('Height'), 'units' => [ 'px', '%' ], 'css' => ['{{element}} ul.products li.product span.onsale' => 'min-height: {{val}}; line-height: {{val}};'], 'req' => [ 'sale_flash' => 'true'], ), 'flash_distance' => array( 'type' => 'slider', 'label' => __('Distance'), 'units' => [ 'px', '%' ], 'max' => 20, 'css' => ['{{element}} ul.products li.product span.onsale' => 'margin: {{val}};'], 'req' => [ 'sale_flash' => 'true'], ), 'flash_position' => array( 'type' => 'radio', 'label' => __('Position'), 'list' => array( 'left' => __('Left'), 'right' => __('Right'), ), 'css' => ['{{element}} ul.products li.product span.onsale' => 'left:auto; right:auto; {{val}} : 0;'], 'req' => [ 'sale_flash' => 'true'], ), ); // TODO: create this form scretch // Product related pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_product_related', array( 'name' => __('Related Upsell Products'), 'group' => 'kkart', 'not_visible' => 1, 'html' => '', 'params' => array( 'select_product' => array( 'type' => 'select', 'label' => __('Product Type'), 'default' => 'related', 'list' => array( 'related' => __('Related'), 'upsell' => __('Upsell'), ), ), 'posts_per_page' => array( 'type' => 'spinner', 'label' => __('Products Per Page'), 'default' => 4, 'max' => 20, 'req' => ['select_product' => 'related'], ), 'columns' => array( 'type' => 'spinner', 'label' => __('Columns'), 'screen' => 1, 'default' => 4, 'min' => 1, 'max' => 12, ), 'order_by' => array( 'type' => 'select', 'label' => __('Order By'), 'default' => 'date', 'list' => array( 'date' => __('Date'), 'title' => __('Title'), 'price' => __('Price'), 'popularity' => __('Popularity'), 'rating' => __('Rating'), 'rand' => __('Random'), 'menu_order' => __('Menu Order'), ), ), 'order' => array( 'type' => 'select', 'label' => __('Order'), 'default' => 'asc', 'list' => array( 'asc' => __('ASC'), 'desc' => __('DESC'), ), ), ), 'products_style' => $products_style, 'heading_style' => $products_heading, 'box_style' => $products_box, 'sale_flash_style' => $products_sale_flash, 'styles' =>[ 'products_style' => __('Products Style'), 'heading_style' => __('Heading Styles'), 'box_style' => __('Box Style'), 'sale_flash_style' => __('Flash Sale Style'), ], ) ); // kkart breadcrumb pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_breadcrumb', array( 'name' => __('Kkart Breadcrumb'), 'group' => 'kkart', 'html' => '
'. kkart_sc_breadcrumb() .'
', 'params' => array( 'color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-breadcrumb' => 'color:{{val}}'], ), 'link_color' => array( 'type' => 'color', 'label' => __('Link Color'), 'css' => ['{{element}} .kkart-breadcrumb > a' => 'color:{{val}}'], ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-breadcrumb' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'css' => ['{{element}} .kkart-breadcrumb' => 'text-align:{{val}}'], 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), ), ), ) ); // Product pages pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_pages', array( 'name' => __('kkart pages'), 'group' => 'kkart', 'html' => '
{{page_content}}
', 'params' => array( 'pages' => array( 'type' => 'select', 'label' => __('Pages'), 'css' => ['{{element}} .kkart-breadcrumb' => 'color:{{val}}'], 'list' => array( '' => __( 'Select' ), 'kkart_cart' => __('Cart Page'), //'product_page' => __('Single Product Page'), 'kkart_checkout' => __('Checkout Page'), 'kkart_order_tracking' => __('Order Tracking Form'), 'kkart_my_account' => __('My Account'), ), ), ), ) ); // TODO: create this form scretch // Product pages pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_product_categories', array( 'name' => __('Product Categories'), 'group' => 'kkart', 'html' => '
{{product_categories}}
', 'params' => array( 'columns' => array( 'type' => 'spinner', 'label' => __('Columns'), 'screen' => 1, 'default' => 4, 'max' => 12, ), 'number' => array( 'type' => 'spinner', 'label' => __('Limit'), 'default' => 4, ), 'source' => array( 'type' => 'select', 'label' => __('Source'), 'list' => array( '' => __('Show All'), 'by_id' => __('Manual Selection'), 'by_parent' => __('By Parent'), 'current_subcategories' => __('Current Sub-Categories'), ), ), 'by_id' => array( 'type' => 'multiselect', 'label' => __('Categories'), 'list' => kkart_get_product_cat(), 'req' => ['source' => 'by_id'], ), 'parent' => array( 'type' => 'select', 'label' => __('Parent'), 'list' => [ '0' => __('Only Top Level') ] + kkart_get_product_cat(), 'req' => ['source' => 'by_parent'], ), 'hide_empty' => array( 'type' => 'checkbox', 'label' => __('Hide Empty'), ), 'orderby' => array( 'type' => 'select', 'label' => __('Order By'), 'default' => 'name', 'list' => array( 'name' => __('Name'), 'slug' => __('Slug'), 'description' => __('Description'), 'count' => __('Count'), ), ), 'order' => array( 'type' => 'select', 'label' => __('Order'), 'default' => 'desc', 'list' => array( 'asc' => __('ASC'), 'desc' => __('DESC'), ), ), ), 'products_style' => array( 'column_gap' => array( 'type' => 'slider', 'label' => __('Column Gap'), 'units' => ['px', '%'], 'screen' => 1, 'default' => 20, 'step' => 0.2, 'max' => 100, 'css' => ['{{element}} ul.products li.product' => 'margin-right: {{val}}'], ), 'row_gap' => array( 'type' => 'slider', 'label' => __('Row Gap'), 'units' => ['px', '%'], 'screen' => 1, 'default' => 20, 'step' => 0.2, 'max' => 100, 'css' => ['{{element}} ul.products li.product' => 'margin-bottom: {{val}}'], ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), 'css' => ['{{element}} ul.products li.product' => 'text-align:{{val}}'], ), 'img_lable' => array( 'type' => 'heading', 'label' => __('Image'), ), 'img_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} a > img' => 'border-style: {{val}}', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'img_border_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} a > img' => 'border-color: {{val}}'], 'show' => ['!img_border_type' => ''], ), 'img_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} a > img' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px' ], 'req' => [ '!img_border_type' => '' ], ), 'img_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} a > img' => 'border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}; -webkit-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};-moz-border-radius: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};', ], ), 'img_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} a > img' => 'margin-bottom: {{val}}'], ), 'title_lable' => array( 'type' => 'heading', 'label' => __('Title'), ), 'title_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-loop-category__title' => 'color: {{val}}'], ), 'title_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-loop-category__title' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'title_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => [ '{{element}} .kkart-loop-category__title' => 'margin-bottom: {{val}}' ], ), 'count_lable' => array( 'type' => 'heading', 'label' => __('Count'), ), 'count_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-loop-category__title .count' => 'color: {{val}}'], ), 'count_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-loop-category__title .count' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), ), 'styles' =>[ 'products_style' => __('Products Style'), ], ) ); // Archives Product pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_product_archives', array( 'name' => __('Product Archives'), 'group' => 'kkart archive', 'has_group' => [ 'section' => 'params', 'prop' => 'elements', 'loop' => 1, ], 'holder' => '.kkart-porduct-archives', 'html' => '
', 'params' => array( 'elements' => array( 'type' => 'group', 'label' => __('Items'), 'sc' => PAGELAYER_SC_PREFIX.'_kkart_archive_item', 'count' => 1, 'item_label' => array( 'default' => __('Items'), ), 'hide' => 1, ), 'cols' => array( 'type' => 'select', 'label' => __('Cols'), 'screen' => 1, 'list' => array( '' => __('Default'), '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', '10' => '10', '11' => '11', '12' => '12', ), 'css' => ['{{element}} .kkart-porduct-archives' => 'grid-template-columns: repeat({{val}}, 1fr);'], ), 'allow_order' => array( 'type' => 'checkbox', 'label' => __('Allow Order'), 'default' => 'true', ), 'show_result' => array( 'type' => 'checkbox', 'label' => __('Show Result Counter'), 'default' => 'true', ), 'no_found' => array( 'type' => 'textarea', 'label' => __('Not Found Message'), 'default' => __('Products not found.'), ), ), 'pagination_style' => array( 'pagination_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'css' => ['{{element}} nav.kkart-pagination' => 'margin-top:{{val}}px'], ), 'pagination_border' => array( 'type' => 'select', 'label' => __('Border'), 'list' => array( '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ), 'css' => ['{{element}} nav.kkart-pagination ul' => 'border-style: {{val}} !important'], ), 'pagination_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} nav.kkart-pagination ul' => 'border-color:{{val}} !important'], 'req' => ['!pagination_border' => ''] ), 'pagination_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} nav.kkart-pagination ul' => 'border-radius:{{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}} !important'], 'req' => ['!pagination_border' => ''] ), 'pagination_border_width' => array( 'type' => 'padding', 'label' => __('Border Size'), 'css' => ['{{element}} nav.kkart-pagination ul' => 'border-top-width: {{val[0]}}px !important; border-right-width: {{val[1]}}px !important; border-bottom-width: {{val[2]}}px !important; border-left-width: {{val[3]}}px !important;'], 'req' => ['!pagination_border' => ''] ), 'pagination_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} nav.kkart-pagination ul' => 'padding: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}'], ), 'pagination_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} nav.kkart-pagination' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'pagination_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} nav.kkart-pagination ul' => 'background-color:{{val}}'] ), 'pagination_shadow' => array( 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} nav.kkart-pagination ul' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[4]}}px {{val[3]}} {{val[5]}};'], ), ), 'pagination_link_style' => array( 'pagination_colors' => array( 'type' => 'radio', 'label' => __('Colors'), 'list' => array( 'normal' => __('Normal'), 'hover' => __('Hover'), 'active' => __('Active'), ), ), 'pagination_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} nav.kkart-pagination ul li a' => 'color:{{val}} !important;'], 'show' => ['pagination_colors' => 'normal'], ), 'pagination_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} nav.kkart-pagination ul li a' => 'background-color:{{val}} !important;'], 'show' => ['pagination_colors' => 'normal'], ), 'pagination_color_hover' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} nav.kkart-pagination ul li a:hover' => 'color:{{val}} !important;'], 'show' => ['pagination_colors' => 'hover'], ), 'pagination_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} nav.kkart-pagination ul li a:hover' => 'background-color:{{val}} !important;'], 'show' => ['pagination_colors' => 'hover'], ), 'pagination_color_active' => array( 'type' => 'color', 'label' => __('Color'), 'css' => [ '{{element}} nav.kkart-pagination ul li span.current' => 'color:{{val}} !important;' ], 'show' => ['pagination_colors' => 'active'], ), 'pagination_bg_color_active' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} nav.kkart-pagination ul li span.current' => 'background-color:{{val}} !important;'], 'show' => ['pagination_colors' => 'active'], ), 'pagination_link_border' => array( 'type' => 'select', 'label' => __('Border'), 'list' => array( '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ), 'css' => ['{{element}} nav.kkart-pagination ul li' => 'border-style: {{val}} !important'], ), 'pagination_link_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} nav.kkart-pagination ul li' => 'border-color:{{val}} !important'], 'req' => ['!pagination_link_border' => ''] ), 'pagination_link_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} nav.kkart-pagination ul li' => 'border-radius:{{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}} !important'], 'req' => ['!pagination_link_border' => ''] ), 'pagination_link_border_width' => array( 'type' => 'padding', 'label' => __('Border Size'), 'css' => ['{{element}} nav.kkart-pagination ul li' => 'border-top-width: {{val[0]}}px !important; border-right-width: {{val[1]}}px !important; border-bottom-width: {{val[2]}}px !important; border-left-width: {{val[3]}}px !important;'], 'req' => ['!pagination_link_border' => ''] ), 'space_between' => array( 'type' => 'slider', 'label' => __('Space Between'), 'css' => ['{{element}} nav.kkart-pagination ul li:not(:last-child)' => 'margin-right:{{val}}px;'], ), 'pagination_link_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'units' => [ 'px', '%' ], 'screen' => 1, 'css' => ['{{element}} nav.kkart-pagination ul li a, {{element}} nav.kkart-pagination ul li span' => 'padding: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}}'], ), ), 'styles' =>[ 'pagination_style' => __('Pagination Style'), 'pagination_link_style' => __('Pagination Link Style') ], ) ); // Archive Products items pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_archive_item', array( 'name' => __('Product Archive Item'), 'group' => 'kkart archive', 'has_group' => [ 'section' => 'params', 'prop' => 'elements', ], 'not_visible' => 1, 'widget_group' => 1, 'holder' => '.kkart-product-archives-item', 'html' => '
', 'params' => array( 'elements' => array( 'type' => 'group', 'label' => __('Inner Row'), 'sc' => PAGELAYER_SC_PREFIX.'_inner_row', 'count' => 1, 'item_label' => array( 'default' => __('Inner Row'), ), 'inner_content' => [ ['pl_col' => [ 'inner_content' => [ ['pl_kkart_sale' => []], ['pl_kkart_archive_thumb' => []], ['pl_kkart_title' => ['atts' => ['link' => 'true']]], ['pl_kkart_price' => []], ['pl_kkart_product_rating' => []], ['pl_kkart_archive_crt_btn' => ['atts' => ['ele_margin' => '5px,5px,0,0', 'ele_custom_pos' => 'true','ele_width' => 'initial']]], ['pl_kkart_buy_now' => ['atts' => ['ele_margin' => '5px,5px,0,0', 'ele_custom_pos' => 'true', 'ele_width' => 'initial']]] ]], ] ], 'hide' => 1, ), ), ) ); // Archive Products thumbnail pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_archive_thumb', array( 'name' => __('Product Archive Thumbnail'), 'icon' => 'fas fa-archive', 'group' => 'kkart archive', 'use_inside' => ['pl_kkart_archive_item'], 'html' => '
{{product_thumb}}
', 'params' => array( 'unlink' => array( 'label' => __('Unlink to Product Page'), 'type' => 'checkbox', 'desc' => __('Image links to a single product. If you wish, you can unlink using this option!'), ), 'gallery' => array( 'label' => __('Gallery'), 'type' => 'checkbox', 'addAttr' => ['{{element}} .kkart-thumbnail-gallery' => 'data-slides-items="1"'], ), 'slider_animation' => array( 'type' => 'select', 'label' => __('Animation In'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-animate-in="{{slider_animation}}"'], 'list' => $pagelayer->anim_in_options, 'req' => ['!gallery' => ''], ), 'slideout_anim' => array( 'type' => 'select', 'label' => __('Animation Out'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-animate-out="{{slideout_anim}}"'], 'list' => $pagelayer->anim_out_options, 'req' => ['!gallery' => ''], ), 'controls' => array( 'type' => 'select', 'label' => __('Slider Controls'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-controls="{{controls}}"'], 'list' => array( '' => __('Arrows and Pager'), 'arrows' => __('Arrows'), 'pager' => __('Pager'), 'none' => __('None'), ), 'req' => ['!gallery' => ''], ), 'pause' => array( 'type' => 'slider', 'label' => __('Slideshow Speed'), 'default' => 5000, 'min' => 200, 'max' => 20000, 'step' => 100, 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-autoplay-timeout="{{pause}}"'], 'req' => ['!gallery' => ''], ), 'speed' => array( 'type' => 'slider', 'label' => __('Animation Speed(s)'), 'addAttr' => ['.pagelayer-image-slider-ul' => 'data-slides-smart-speed="{{speed}}"'], 'default' => 800, 'min' => 200, 'max' => 10000, 'step' => 100, 'req' => ['!gallery' => ''], ), 'loop' => array( 'type' => 'checkbox', 'label' => __('Loop'), 'desc' => __('Loop images in slider'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-loop="{{loop}}"'], 'req' => ['!gallery' => ''], ), 'adaptive_height' => array( 'type' => 'checkbox', 'label' => __('Slider Height'), 'desc' => __('The slider height should change on the fly according to the current slide'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-auto-height="{{adaptive_height}}"'], 'req' => ['!gallery' => ''], ), 'auto' => array( 'type' => 'checkbox', 'label' => __('Auto Start'), 'desc' => __('Check to auto start slider'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-autoplay="{{auto}}"'], 'req' => ['!gallery' => ''], ), 'auto_hover' => [ 'type' => 'checkbox', 'label' => __('Pause on hover'), 'desc' => __('If enabled, the slider will pause when you hover over the slider'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-autoplay-hover-pause="{{auto_hover}}"'], 'req' => ['!gallery' => ''], ], ), 'image_styles' => array( 'box_heihgt' => array( 'type' => 'slider', 'label' => __('Image Box Height'), 'min' => 0, 'screen' => 1, 'units' => ['px', 'em'], 'css' => ['{{element}} .kkart-product-thumbnail' => 'height:{{val}} '], ), 'img_width' => array( 'type' => 'slider', 'label' => __('Image Width'), 'min' => 0, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-product-thumbnail .kkart-thumb-img' => 'width:{{val}}%'], ), 'img_heihgt' => array( 'type' => 'slider', 'label' => __('Image Height'), 'min' => 0, 'screen' => 1, 'units' => ['%', 'px'], 'css' => ['{{element}} .kkart-product-thumbnail .kkart-thumb-img' => 'height:{{val}};object-fit:cover;'], ), 'img_align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'screen' => 1, 'list' => array( 'flex-start' => __('Left'), 'center' => __('Center'), 'flex-end' => __('Right'), ), 'css' => ['{{element}} .kkart-product-thumbnail' => 'justify-content:{{val}}'], ), 'img_align_vert' => array( 'type' => 'radio', 'label' => __('Vertical Align'), 'screen' => 1, 'list' => array( 'flex-start' => __('Left'), 'center' => __('Center'), 'flex-end' => __('Right'), ), 'css' => ['{{element}} .kkart-product-thumbnail' => 'align-items:{{val}}'], ), ), 'arrow_styles' => $pagelayer->slider_arrow_styles, 'pager_styles' => $pagelayer->slider_pager_styles, 'styles' => [ 'image_styles' => __('Image Styles'), 'arrow_styles' => __('Arrow Styles'), 'pager_styles' => __('Pager Styles'), ], ) ); // Archive Products add to cart button pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_archive_crt_btn', array( 'name' => __('Archive Add To Cart'), 'group' => 'kkart archive', 'use_inside' => ['pl_kkart_archive_item'], 'html' => '
{{archive_crt_btn_text}}
{{kkart_quantity_holder}}
{{kkart_view_cart}}
', 'params' => array( 'archive_crt_btn_text' => array( 'type' => 'text', 'label' => __('Button Text'), 'default' => 'Add To Cart', 'edit' => '.kkart-archive-crt-btn', ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-archive-crt-btn' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'size' => array( 'type' => 'select', 'label' => __('Size'), 'default' => 'pagelayer-btn-custom', 'list' => array( 'pagelayer-btn-mini' => __('Mini'), 'pagelayer-btn-small' => __('Small'), 'pagelayer-btn-large' => __('Large'), 'pagelayer-btn-extra-large' => __('Extra Large'), 'pagelayer-btn-double-large' => __('Double Large'), 'pagelayer-btn-custom' => __('Custom'), ), ), 'custom_size' => array( 'type' => 'spinner', 'label' => __('Custom Size'), 'min' => 1, 'max' => 100, 'default' => 10, 'screen' => 1, 'css' => ['{{element}} .kkart-archive-crt-btn' => 'padding: calc({{val}}px / 2) {{val}}px !important;'], 'req' => array( 'size' => ['pagelayer-btn-custom'], ), ), 'btn_type' => array( 'type' => 'select', 'label' => __('Button type'), 'default' => 'pagelayer-btn-default', 'list' => array( 'pagelayer-btn-default' => __('Default'), 'pagelayer-btn-primary' => __('Primary'), 'pagelayer-btn-secondary' => __('Secondary'), 'pagelayer-btn-success' => __('Success'), 'pagelayer-btn-info' => __('Information'), 'pagelayer-btn-warning' => __('Warning'), 'pagelayer-btn-danger' => __('Danger'), 'pagelayer-btn-dark' => __('Dark'), 'pagelayer-btn-light' => __('Light'), 'pagelayer-btn-link' => __('Link'), 'pagelayer-btn-custom' => __('Custom') ), ), 'btn_hover' => array( 'type' => 'radio', 'label' => __('State'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), 'req' => array( 'btn_type' => ['pagelayer-btn-custom'], ), ), 'btn_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-archive-crt-btn' => 'background-color: {{val}};', ], 'req' => array( 'btn_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => '' ), ), 'btn_color' => array( 'type' => 'color', 'label' => __('Button Color'), 'css' => ['{{element}} .kkart-archive-crt-btn' => 'color: {{val}};'], 'req' => array( 'btn_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => '' ), ), 'btn_hover_delay' => array( 'type' => 'spinner', 'label' => __('Button Hover Delay'), 'desc' => __('Time to delay the hover in ms'), 'min' => 0, 'step' => 100, 'max' => 5000, 'default' => 400, 'css' => ['{{element}} .kkart-archive-crt-btn' => '-webkit-transition: all {{val}}ms !important; transition: all {{val}}ms !important;'], 'show' => array( 'btn_type' => ['pagelayer-btn-custom'], 'btn_hover' => 'hover' ), ), 'btn_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Hover Color'), 'css' => [ '{{element}} .kkart-archive-crt-btn:hover' => 'background-color: {{val}};', ], 'req' => array( 'btn_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => 'hover', ), ), 'btn_color_hover' => array( 'type' => 'color', 'label' => __('Hover Color'), 'css' => ['{{element}} .kkart-archive-crt-btn:hover' => 'color: {{val}};'], 'req' => array( 'btn_type' => ['pagelayer-btn-custom'], ), 'show' => array( 'btn_hover' => 'hover' ), ), 'btn_shadow' => array( 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} .kkart-archive-crt-btn' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[4]}}px {{val[3]}} {{val[5]}} !important;'], ), 'btn_shadow_hover' => array( // This is actually box shadow hover 'type' => 'box_shadow', 'label' => __('Box Shadow Hover'), 'css' => ['{{element}} .kkart-archive-crt-btn:hover' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}} !important;'], ), 'show_view_cart' => array( 'type' => 'checkbox', 'label' => __('Show view cart for editor'), ), 'show_quantity_holder' => array( 'type' => 'checkbox', 'label' => __('Show quantity holder for editor'), ) ), 'btn_border_style' => [ 'btn_bor_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-archive-crt-btn' => 'border-style: {{val}};', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-archive-crt-btn' => 'border-color: {{val}};'], 'req' => array( '!btn_border_type' => '' ), 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-archive-crt-btn' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => [ '!btn_border_type' => '' ], 'show' => array( 'btn_bor_hover' => '' ), ), 'btn_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-archive-crt-btn' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!btn_border_type' => '', ), 'show' => array( 'btn_bor_hover' => '', ), ), 'btn_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-archive-crt-btn:hover' => 'border-style: {{val}}' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color Hover'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-archive-crt-btn:hover' => 'border-color: {{val}};'], 'req' => array( '!btn_border_type_hover' => '' ), 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width Hover'), 'screen' => 1, 'css' => [ '{{element}} .kkart-archive-crt-btn:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px;' ], 'req' => [ '!btn_border_type_hover' => '' ], 'show' => array( 'btn_bor_hover' => 'hover' ), ), 'btn_border_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius Hover'), 'screen' => 1, 'css' => ['{{element}} .kkart-archive-crt-btn:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!btn_border_type_hover' => '', ), 'show' => array( 'btn_bor_hover' => 'hover', ), ), ], 'view_cart_btn_style' => array( 'view_crt_btn_text' => array( 'type' => 'text', 'label' => __('View Cart Text'), 'default' => __('View cart'), 'edit' => '.kkart-view-btn', 'addAttr' => ['{{element}} .kkart-crt-btn-holder' => 'data-view-btn-text="{{view_crt_btn_text}}"'] ), 'view_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-view-btn' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'view_custom_size' => array( 'type' => 'spinner', 'label' => __('Custom Size'), 'min' => 1, 'max' => 100, 'default' => 10, 'screen' => 1, 'css' => ['{{element}} .kkart-view-btn' => 'padding: calc({{val}}px / 2) {{val}}px !important;'], ), 'view_btn_hover' => array( 'type' => 'radio', 'label' => __('State'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ), ), 'view_btn_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => [ '{{element}} .kkart-view-btn' => 'background-color: {{val}};', ], 'show' => array( 'view_btn_hover' => '' ), ), 'view_btn_color' => array( 'type' => 'color', 'label' => __('Button Color'), 'css' => ['{{element}} .kkart-view-btn' => 'color: {{val}};'], 'show' => array( 'view_btn_hover' => '' ), ), 'view_btn_hover_delay' => array( 'type' => 'spinner', 'label' => __('Button Hover Delay'), 'desc' => __('Time to delay the hover in ms'), 'min' => 0, 'step' => 100, 'max' => 5000, 'default' => 400, 'css' => ['{{element}} .kkart-view-btn' => '-webkit-transition: all {{val}}ms !important; transition: all {{val}}ms !important;'], 'show' => array( 'view_btn_hover' => 'hover' ), ), 'view_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Hover Color'), 'css' => [ '{{element}} .kkart-view-btn:hover' => 'background-color: {{val}};', ], 'show' => array( 'view_btn_hover' => 'hover', ), ), 'view_btn_color_hover' => array( 'type' => 'color', 'label' => __('Hover Color'), 'css' => ['{{element}} .kkart-view-btn:hover' => 'color: {{val}};'], 'show' => array( 'view_btn_hover' => 'hover' ), ), 'view_btn_shadow' => array( 'type' => 'box_shadow', 'label' => __('Shadow'), 'css' => ['{{element}} .kkart-view-btn' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[4]}}px {{val[3]}} {{val[5]}} !important;'], ), 'view_btn_shadow_hover' => array( // This is actually box shadow hover 'type' => 'box_shadow', 'label' => __('Box Shadow Hover'), 'css' => ['{{element}} .kkart-view-btn:hover' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}} !important;'], ), 'veiw_cart_spacing' => array( 'type' => 'spinner', 'label' => __('Spacing'), 'css' => ['{{element}} .kkart-view-btn-holder' => 'margin-left:{{val}}px; margin-right:{{val}}px'], ), ), 'view_cart_border_style' => array( 'view_btn_bor_hover' => array( 'type' => 'radio', 'label' => __('State'), 'default' => '', 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'view_btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-view-btn' => 'border-style: {{val}};', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'view_btn_bor_hover' => '' ), ), 'view_btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-view-btn' => 'border-color: {{val}};'], 'req' => array( '!view_btn_border_type' => '' ), 'show' => array( 'view_btn_bor_hover' => '' ), ), 'view_btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-view-btn' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => [ '!view_btn_border_type' => '' ], 'show' => array( 'view_btn_bor_hover' => '' ), ), 'view_btn_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-view-btn' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!view_btn_border_type' => '', ), 'show' => array( 'view_btn_bor_hover' => '', ), ), 'view_border_type_hover' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-view-btn:hover' => 'border-style: {{val}}' ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'show' => array( 'view_btn_bor_hover' => 'hover' ), ), 'view_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color Hover'), 'css' => ['{{element}} .kkart-view-btn:hover' => 'border-color: {{val}};'], 'req' => array( '!view_border_type_hover' => '' ), 'show' => array( 'view_btn_bor_hover' => 'hover' ), ), 'view_border_width_hover' => array( 'type' => 'padding', 'label' => __('Border Width Hover'), 'screen' => 1, 'css' => [ '{{element}} .kkart-view-btn:hover' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px;' ], 'req' => [ '!view_border_type_hover' => '' ], 'show' => array( 'view_btn_bor_hover' => 'hover' ), ), 'view_border_radius_hover' => array( 'type' => 'padding', 'label' => __('Border Radius Hover'), 'screen' => 1, 'css' => ['{{element}} .kkart-view-btn:hover' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!view_border_type_hover' => '', ), 'show' => array( 'view_btn_bor_hover' => 'hover', ), ), ), 'quantity_holder_style' => array( 'quantityh_background_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .kkart-quantity-holder' => 'background-color:{{val}}'] ), 'quantityh_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .kkart-quantity-holder' => 'border-style: {{val}};'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'quantityh_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-quantity-holder' => 'border-color: {{val}};'], 'req' => ['!quantityh_border_type' => ''], ), 'quantityh_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity-holder' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!quantityh_border_type' => ''], ), 'quantityh_borderh_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity-holder' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!quantityh_border_type' => ''], ), 'quantityh_padding' =>array( 'type' => 'slider', 'label' => __('Padding'), 'css' => ['{{element}} .kkart-quantity-holder' => 'padding:{{val}}px'] ), 'quantityh_spacing' => array( 'type'=> 'spinner', 'label' => __('Space Between'), 'css' => ['{{element}} .kkart-quantity-close' => 'margin-left:{{val}}px;'], ), ), 'quantity-style' => array( 'quantity_color' => array( 'type' => 'color', 'label' => __('Text Color'), 'css' => ['{{element}} .kkart-quantity, {{element}} .kkart-quantity-input' => 'color:{{val}}'] ), 'quantity_background_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .kkart-quantity' => 'background-color:{{val}}'] ), 'quantity_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .kkart-quantity' => 'border-style: {{val}};', '{{element}} .kkart-quantity-input' => 'border-left-style: {{val}}; border-right-style:{{val}};'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'quantity_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-quantity' => 'border-color: {{val}};', '{{element}} .kkart-quantity-input' => 'border-left-color: {{val}}; border-right-color: {{val}};'], 'req' => ['!quantity_border_type' => ''], ), 'quantity_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px', '{{element}} .kkart-quantity-input' => 'border-left-width: {{val[3]}}px; border-right-width:{{val[1]}}px;'], 'req' => ['!quantity_border_type' => ''], ), 'quantity_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!quantity_border_type' => ''], ), 'quantity_input_width' =>array( 'type' => 'spinner', 'label' => __('Input Text Width'), 'min' => 2, 'step' => 0.1, 'css' => ['{{element}} .kkart-quantity-input' => 'width:{{val}}em !important'], ), 'quantity_size' => array( 'type' => 'spinner', 'label' => __('Size'), 'min' => 1, 'step' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-minus, {{element}} .kkart-plus, {{element}} .kkart-quantity-input' => 'padding: calc({{val}}px / 2) {{val}}px !important;'], ), ), 'quantity-close-style' => array( 'quantityc_color' => array( 'type' => 'color', 'label' => __('Text Color'), 'css' => ['{{element}} .kkart-quantity-close' => 'color:{{val}}'] ), 'quantityc_background_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .kkart-quantity-close' => 'background-color:{{val}}'] ), 'quantityc_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-quantity-close' => 'border-style: {{val}};', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'quantityc_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-quantity-close' => 'border-color: {{val}};'], 'req' => ['!quantityc_border_type' => ''], ), 'quantityc_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity-close' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => ['!quantityc_border_type' => ''], ), 'quantityc_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-quantity-close' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => ['!quantityc_border_type' => ''], ), 'quantityc_size' => array( 'type' => 'spinner', 'label' => __('Size'), 'min' => 1, 'step' => 1, 'max' => 100, 'screen' => 1, 'css' => ['{{element}} .kkart-quantity-close' => 'padding: calc({{val}}px / 2) {{val}}px !important;'], ), ), 'styles' =>[ 'btn_border_style' => __('Button Border Style'), 'quantity_holder_style' => __('Quantity Holder Style'), 'quantity-style' => __('Quantity Style'), 'quantity-close-style' => __('Quantity Close Style'), 'view_cart_btn_style' => __('View Cart Button'), 'view_cart_border_style' => __('View Cart Border'), ], ) ); // Archive Products add to cart button pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_sale', array( 'name' => __('Sale Flash'), 'group' => 'kkart archive', 'use_inside' => ['pl_kkart_archive_item'], 'html' => '
{{sale_discount}}  {{sale_text}}
', 'params' => array( 'show_discount' => array( 'type' => 'checkbox', 'label' => __('Show Discount'), 'default' => 'true', ), 'sale_text' => array( 'type' => 'text', 'label' => __('Text'), 'default' => __('Off'), 'edit' => '.kkart-sale-text' ), 'sale_text_position' => array( 'type' => 'radio', 'label' => __('Text Alignment'), 'list' => array( 'kkart-sale-text-left' => __('Left'), '' => __('Right') ), 'addClass' => '{{val}}', 'css' => '{{val}}', 'show' => ['!show_discount' => ''], ), 'typography' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => ['{{element}} .kkart-onsale' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'background_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .kkart-onsale' => 'background-color:{{val}};'], ), 'color' => array( 'type' => 'color', 'label' => __('Text Color'), 'css' => ['{{element}} .kkart-onsale' => 'color:{{val}};'], ), ), 'sale_style' => array( 'sale_type' => array( 'type' => 'select', 'label' => __('Badge Type'), 'list' => array( 'kkart-onsale-circle' => __('Circle'), 'kkart-onsale-ribbon' => __('Ribbon'), ), 'default' => 'kkart-onsale-circle', ), 'width' => array( 'type' => 'slider', 'label' => __('Width'), 'max' => 1200, 'units' => ['px', 'em', '%'], 'screen' => 1, 'css' => ['{{element}} .kkart-onsale' => 'width: {{val}};'], ), 'height' => array( 'type' => 'slider', 'label' => __('Height'), 'max' => 1200, 'units' => ['px', 'em', '%'], 'screen' => 1, 'css' => ['{{element}} .kkart-onsale' => 'height: {{val}};'], ), 'spacing' => array( 'type' => 'spinner', 'label' => __('Spacing'), 'default' => '2', 'min' => '0', 'css' => ['{{element}} .kkart-onsale' => 'padding: {{val}}px'], ), 'sale_position' => array( 'type' => 'radio', 'label' => __('Position'), 'default' => 'right', 'list' => array( 'left' => __('Left'), 'right' => __('Right'), ), ), 'rotate' => array( 'type' => 'spinner', 'label' => __('Rotate'), 'css' => ['{{element}} .kkart-onsale-ribbon' => 'transform:rotate({{val}}deg);'], 'req' => array( '!sale_type' => ['kkart-onsale-circle'], ), ), ), 'border_style' => [ 'border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => [ '{{element}} .kkart-onsale' => 'border-style: {{val}};', ], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .kkart-onsale' => 'border-color: {{val}};'], 'req' => array( '!border_type' => '' ), ), 'border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-onsale' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], 'req' => [ '!border_type' => '' ], ), 'border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'screen' => 1, 'css' => ['{{element}} .kkart-onsale' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;'], 'req' => array( '!border_type' => '' ), 'show' => array( '!sale_type' => 'kkart-onsale-circle', ), ), ], 'styles' => array( 'sale_style' => __('Sale Style'), 'border_style' => __('Border Style'), ), ) ); // Product Title pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_title', array( 'name' => __('Product Title'), 'group' => 'kkart', 'use_inside' => ['pl_kkart_archive_item'], 'edit_props' => ['.kkart-title' => 'post_title'], 'html' => '', 'params' => array( 'before' => array( 'type' => 'text', 'label' => __('Before'), 'np' => 1, ), 'after' => array( 'type' => 'text', 'label' => __('After'), 'np' => 1, ), 'link' => array( 'type' => 'checkbox', 'label' => __('Link to Product Page'), 'default' => true, ), 'title_colors' => array( 'type' => 'radio', 'label' => __('Colors'), 'list' => array( '' => __('Normal'), 'hover' => __('Hover'), ) ), 'color' => array( 'type' => 'color', 'label' => __('Color'), 'default' => '#0986c0', 'css' => ['{{element}} .kkart-product-title, {{element}} .kkart-product-title *' => 'color:{{val}}'], 'show' => ['title_colors' => ''] ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'default' => ',25,,700,,,solid,,,,', 'screen' => 1, 'css' => ['{{element}} .kkart-product-title' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], 'show' => ['title_colors' => ''] ), 'color_hover' => array( 'type' => 'color', 'label' => __('Color'), 'default' => '#0986c0', 'css' => ['{{element}} .kkart-product-title:hover, {{element}} .kkart-product-title:hover *' => 'color:{{val}}'], 'show' => ['title_colors' => 'hover'] ), 'typo_hover' => array( 'type' => 'typography', 'label' => __('Typography'), 'screen' => 1, 'css' => ['{{element}} .kkart-product-title:hover' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], 'show' => ['title_colors' => 'hover'] ), 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'list' => [ 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ], 'css' => ['{{element}} .kkart-product-title' => 'text-align: {{val}}'], ), ) ) ); // TODO: create this // Products pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_products', array( 'name' => __('Products'), 'group' => 'kkart', 'has_group' => [ 'section' => 'params', 'prop' => 'elements', 'loop' => 1, ], 'holder' => '.pagelayer-products-container', 'child_selector' => '>.pagelayer-owl-stage-outer>.pagelayer-owl-stage>.pagelayer-owl-item', 'html' => '

{{product_title}}

', 'params' => array( 'elements' => array( 'type' => 'group', 'label' => __('Items'), 'sc' => PAGELAYER_SC_PREFIX.'_kkart_archive_item', 'count' => 1, 'item_label' => array( 'default' => __('Items'), ), 'hide' => 1, ), 'view' => array( 'type' => 'select', 'label' => __('View Type'), 'list' => array( '' => __('Grid'), 'slider' => __('Slider'), ), 'addClass' => ['{{element}} .pagelayer-products-container' => 'pagelayer-owl-holder pagelayer-owl-carousel pagelayer-owl-theme'] ), 'cols' => array( 'type' => 'select', 'label' => __('Cols'), 'screen' => 1, 'list' => array( '' => __('Default'), '1' => '1', '2' => '2', '3' => '3', '4' => '4', '5' => '5', '6' => '6', '7' => '7', '8' => '8', '9' => '9', '10' => '10', '11' => '11', '12' => '12', ), 'css' => ['{{element}} .pagelayer-products-container' => 'grid-template-columns: repeat({{val}}, 1fr);'], 'req' => ['view' => ''], ), 'limit' => array( 'type' => 'spinner', 'label' => __('Total number of products'), 'desc' => __('Default 12 products will be shown'), ), 'product_title' => array( 'type' => 'text', 'label' => __('Title'), 'default' => __('You may also like this'), ), 'no_found' => array( 'type' => 'textarea', 'label' => __('Not Found Messages'), 'default' => __('Products not found.'), ), ), 'query' => array( 'source' => array( 'type' => 'select', 'label' => __('Source'), 'default' => 'recent_products', 'list' => array( 'pagelayer_current_query' => __('Currunt Query'), 'recent_products' => __('Recent Products'), 'sale_products' => __('Sale Products'), 'best_selling_products' => __('Best Selling Products'), 'top_rated_products' => __('Top Rated Products'), 'featured_products' => __('Featured Product'), 'upsell_product' => __('Upsell Product'), 'cross_sell_product' => __('Cross sell Product'), 'related_products' => __('Related Products'), 'by_id' => __('Manual Selection'), ), ), 'ids' => array( 'type' => 'multiselect', 'label' => __('Products'), 'list' => pagelayer_post_list_by_type('product'), 'req' => ['source' => 'by_id'], ), 'orderby' => array( 'type' => 'select', 'label' => __('Order By'), 'default' => 'date', 'list' => array( 'date' => __('Date'), 'title' => __('Title'), 'price' => __('Price'), 'popularity' => __('Popularity'), 'rating' => __('Rating'), 'rand' => __('Rand'), 'menu_order' => __('Menu Order'), ), ), 'order' => array( 'type' => 'select', 'label' => __('Order'), 'default' => 'ASC', 'list' => array( 'ASC' => __('ASC'), 'DESC' => __('DESC'), ), ), ), 'slider_options' => array( 'slide_items' => array( 'type' => 'spinner', 'label' => __pl('number_of_items'), 'min' => 1, 'step' => 1, 'max' => 10, 'default' => 3, 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-items="{{slide_items}}"'], ), 'slider_animation' => array( 'type' => 'select', 'label' => __pl('animation_in'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-animate-in="{{slider_animation}}"'], 'list' => $pagelayer->anim_in_options, 'req' => ['slide_items' => '1'] ), 'slideout_anim' => array( 'type' => 'select', 'label' => __pl('animation_out'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-animate-out="{{slideout_anim}}"'], 'list' => $pagelayer->anim_out_options, 'req' => ['slide_items' => '1'] ), 'controls' => array( 'type' => 'select', 'label' => __pl('slider_controls'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-controls="{{controls}}"'], 'list' => array( '' => __pl('Arrows and Pager'), 'arrows' => __pl('Arrows'), 'pager' => __pl('Pager'), 'none' => __pl('none'), ) ), 'pause' => array( 'type' => 'slider', 'label' => __pl('image_slider_slideshow_speed_label'), 'default' => 5000, 'min' => 200, 'max' => 20000, 'step' => 100, 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-autoplay-timeout="{{pause}}"'], ), 'speed' => array( 'type' => 'slider', 'label' => __pl('slider_animation_speed'), 'addAttr' => ['.pagelayer-products-container' => 'data-slides-smart-speed="{{speed}}"'], 'default' => 800, 'min' => 200, 'max' => 10000, 'step' => 100 ), 'loop' => array( 'type' => 'checkbox', 'label' => __pl('image_slider_loop'), 'desc' => __pl('image_slider_loop_desc'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-loop="{{loop}}"'], ), 'adaptive_height' => array( 'type' => 'checkbox', 'label' => __pl('slider_height'), 'desc' => __pl('slider_height_desc'), 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-auto-height="{{adaptive_height}}"'], ), 'auto' => array( 'type' => 'checkbox', 'label' => __pl('image_slider_auto'), 'desc' => __pl('image_slider_auto_desc'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-autoplay="{{auto}}"'], ), 'auto_hover' => [ 'type' => 'checkbox', 'label' => __pl('auto_hover'), 'desc' => __pl('auto_hover_desc'), 'default' => 'true', 'addAttr' => ['{{element}} .pagelayer-owl-holder' => 'data-slides-autoplay-hover-pause="{{auto_hover}}"'], ], ), 'arrow_styles' => $pagelayer->slider_arrow_styles, 'pager_styles' => $pagelayer->slider_pager_styles, 'product_title_style' => array( 'pts_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .pagelayer-product-title' => 'color:{{val}}'], ), 'pts_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .pagelayer-product-title' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), ), 'no_found_style' => array( 'nf_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .pagelayer-product-no-found' => 'color:{{val}}'], ), 'nf_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .pagelayer-product-no-found' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), ), 'styles' =>[ 'query' => __('Query'), 'slider_options' => __('Slider Options'), 'arrow_styles' => __('Arrow Styles'), 'pager_styles' => __('Pager Styles'), 'no_found_style' => __('No Found Style'), 'product_title_style' => __('Title Styles'), ], ) ); // TODO: create this // Product Archives description pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_product_archives_desc', array( 'name' => __('Product Archives Description'), 'group' => 'kkart', 'not_visible' => 1, 'html' => '
'. kkart_get_product_archives_desc() .'
', 'params' => array( 'align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), 'css' => ['{{element}} .pagelayer-archives-desc-container' => 'text-align:{{val}}'], ), 'color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-product-details__short-description' => 'color:{{val}}'], ), 'typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-product-details__short-description' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), ), ) ); // TODO: create this // Product Additional Information pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_addi_info', array( 'name' => __('Additional Information'), 'group' => 'kkart', 'not_visible' => 1, 'html' => '

{{product_addi_info_heading}}

{{product_addi_info}}
', 'params' => array( 'label_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-product-attributes-item__label' => 'color:{{val}}'], ), 'label_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-product-attributes-item__label' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'value_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-product-attributes-item__value' => 'color:{{val}}'], ), 'value_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-product-attributes-item__value' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'heading' => array( 'type' => 'checkbox', 'label' => __('Heading Style'), 'default' => 'true', 'addAttr' => ['{{element}} .kkart-addi-info-container' => 'pagelayer-show-heading="{{heading}}"'], ), 'heading_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-addi-info-container h2' => 'color:{{val}}'], 'req' => ['heading' => 'true'], ), 'heading_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-addi-info-container h2' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], 'req' => ['heading' => 'true'], ), ), ) ); // TODO: create this // Product Additional Information pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_data_tabs', array( 'name' => __('Product Data Tabs'), 'group' => 'kkart', 'not_visible' => 1, 'html' => '
'. kkart_get_product_data_tabs() .'
', 'params' => array( 'tabs_colors' => array( 'type' => 'radio', 'label' => __('Colors'), 'list' => array( 'normal' => __('Normal'), 'active' => __('Active'), ), ), 'tabs_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['.kkart {{element}} .kkart-tabs ul.wc-tabs li a' => 'color:{{val}}'], 'show' => ['tabs_colors' => 'normal'], ), 'tabs_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['.kkart {{element}} .kkart-tabs ul.wc-tabs li' => 'background-color:{{val}}'], 'show' => ['tabs_colors' => 'normal'], ), 'tabs_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => [ '.kkart {{element}} .kkart-tabs ul.wc-tabs li' => 'border-color:{{val}}', '.kkart {{element}} .kkart-tabs .kkart-Tabs-panel' => 'border-color:{{val}}' ], 'show' => ['tabs_colors' => 'normal'], ), 'tabs_color_active' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['.kkart {{element}} .kkart-tabs ul.wc-tabs li.active a' => 'color:{{val}}'], 'show' => ['tabs_colors' => 'active'], ), 'tabs_bg_color_active' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['.kkart {{element}} .kkart-tabs ul.wc-tabs li.active' => 'background-color:{{val}}'], 'show' => ['tabs_colors' => 'active'], ), 'tabs_border_color_active' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => [ '.kkart {{element}} .kkart-tabs .kkart-Tabs-panel' => 'border-color: {{val}}', '.kkart {{element}} .kkart-tabs ul.wc-tabs li.active' => 'border-color: {{val}}' ], 'show' => ['tabs_colors' => 'active'], ), 'tabs_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '.kkart {{element}} .kkart-tabs ul.wc-tabs li a' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'border_radius' => array( 'type' => 'slider', 'label' => __('Border Radius'), 'css' => ['.kkart {{element}} .kkart-tabs ul.wc-tabs li' => 'border-radius: {{val}}px'], ), ), 'panel_style' => array( 'panel_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['.kkart {{element}} .kkart-tabs .kkart-Tabs-panel' => 'color: {{val}}'], ), 'panel_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '.kkart {{element}} .kkart-tabs .kkart-Tabs-panel' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'panel_heading' => array( 'type' => 'heading', 'label' => __('Heading Style'), ), 'panel_heading_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['.kkart {{element}} .kkart-tabs .kkart-Tabs-panel h2' => 'color: {{val}}'], ), 'panel_heading_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '.kkart {{element}} .kkart-tabs .kkart-Tabs-panel h2' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'panel_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'css' => ['.kkart {{element}} .kkart-tabs .kkart-Tabs-panel' => 'border-width: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; margin-top: -{{val[0]}}px'], ), 'panel_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'css' => [ '.kkart {{element}} .kkart-tabs .kkart-Tabs-panel' => 'border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px; -webkit-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;-moz-border-radius: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px;', '.kkart {{element}} .kkart-tabs ul.wc-tabs' => 'margin-left: {{val[0]}}px; margin-right: {{val[1]}};' ], ), 'panel_shadow' => array( 'type' => 'box_shadow', 'label' => __('Box Shadow'), 'css' => ['.kkart {{element}} .kkart-tabs .kkart-Tabs-panel' => 'box-shadow: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}};'], ), ), 'styles' => array( 'panel_style' => __('Panel Style'), ), ) ); // kkart Menu cart pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_menu_cart', array( 'name' => __('Kkart Menu Cart'), 'icon' => 'fa fa-shopping-cart', 'group' => 'kkart', 'html' => '
'. kkart_sc_menu_cart_html() .'
', 'params' => array( 'icon_type' => array( 'type' => 'select', 'label' => __('Icon'), 'default' => 'fa fa-shopping-cart', 'list' => array( 'fa fa-shopping-cart' => __('Cart'), 'fa fa-shopping-basket' => __('Basket'), 'fa fa-shopping-bag' => __('Bag'), ), ), 'items_indicator' => array( 'type' => 'select', 'label' => __('Items Indicator'), 'default' => 'bubble', 'list' => array( '' => __('None'), 'bubble' => __('Bubble'), 'plain' => __('Plain'), ), 'addAttr' => [ '{{element}} .pagelayer-menu-cart-toggle' => 'pagelayer-icon="{{items_indicator}}"'], ), 'empty_indicator' => array( 'type' => 'checkbox', 'label' => __('Empty Indicator'), 'addAttr' => ['{{element}} .pagelayer-menu-cart-toggle' => 'pagelayer-empty-indicator="{{empty_indicator}}"'], ), 'sub_total' => array( 'type' => 'checkbox', 'label' => __('Hide Sub Total'), 'css' => ['{{element}} .pagelayer-cart-button-text' => 'display:none;'] ), 'cart_align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'default' => 'left', 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), 'css' => [ '{{element}} .pagelayer-menu-cart-toggle' => 'text-align:{{val}}' ], ), ), 'mini_cart_style' => array( 'mini_cart_colors' => array( 'type' => 'radio', 'label' => '', 'list' => array( 'normal' => __('Normal'), 'hover' => __('Hover'), ), ), 'mini_cart_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .pagelayer-cart-button' => 'color:{{val}}'], 'show' => ['mini_cart_colors' => 'normal'], ), 'cart_icon_color' => array( 'type' => 'color', 'label' => __('Cart Icon Color'), 'css' => ['{{element}} .pagelayer-cart-button-icon' => 'color:{{val}}'], 'show' => ['mini_cart_colors' => 'normal'], ), 'mini_cart_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .pagelayer-cart-button' => 'background-color:{{val}}'], 'show' => ['mini_cart_colors' => 'normal'], ), 'mini_cart_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .pagelayer-cart-button' => 'border-color:{{val}}'], 'show' => ['mini_cart_colors' => 'normal'], ), 'mini_cart_color_hover' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .pagelayer-cart-button:hover' => 'color:{{val}}'], 'show' => ['mini_cart_colors' => 'hover'], ), 'cart_icon_color_hover' => array( 'type' => 'color', 'label' => __('Cart Icon Color'), 'css' => ['{{element}} .pagelayer-cart-button-icon:hover' => 'color:{{val}}'], 'show' => ['mini_cart_colors' => 'hover'], ), 'cart_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .pagelayer-cart-button:hover' => 'background-color:{{val}}'], 'show' => ['mini_cart_colors' => 'hover'], ), 'cart_border_color_hover' => array( 'type' => 'color', 'label' => __('Border Color'), 'css' => ['{{element}} .pagelayer-cart-button:hover' => 'border-color:{{val}}'], 'show' => ['mini_cart_colors' => 'hover'], ), 'cart_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .pagelayer-cart-button' => 'border-style: {{val}}'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'cart_border_width' => array( 'type' => 'slider', 'label' => __('Border Width'), 'css' => ['{{element}} .pagelayer-cart-button' => 'border-width:{{val}}px'], 'req' => ['!cart_border_type' => ''], ), 'cart_border_radius' => array( 'type' => 'slider', 'label' => __('Border Radius'), 'units' => [ 'px', 'em', '%' ], 'css' => ['{{element}} .pagelayer-cart-button' => 'border-radius:{{val}}'], ), 'cart_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .pagelayer-cart-button' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'mini_cart_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'units' => [ 'px', 'em', '%' ], 'css' => ['{{element}} .pagelayer-cart-button' => 'padding: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}};'], ), 'mini_cart_icon' => array( 'type' => 'heading', 'label' => __('Icon'), ), 'mini_icon_size' => array( 'type' => 'slider', 'label' => __('Size'), 'units' => [ 'px', 'em' ], 'css' => ['{{element}} .pagelayer-cart-button-icon' => 'font-size:{{val}}'], ), 'mini_icon_spacing' => array( 'type' => 'slider', 'label' => __('Spacing'), 'units' => [ 'px', 'em' ], 'min' => 0, 'max' => 50, 'css' => [ 'body:not(.rtl) {{element}} .pagelayer-cart-button-text' => 'margin-right: {{val}}', 'body.rtl {{element}} .pagelayer-cart-button-text' => 'margin-left: {{val}}', ], ), 'mini_bubble_icon' => array( 'type' => 'heading', 'label' => __('Bubble'), 'req' => ['items_indicator' => 'bubble'], ), 'bubble_colors' => array( 'type' => 'radio', 'label' => '', 'default' => 'normal', 'list' => array( 'normal' => __('Normal'), 'hover' => __('Hover'), ), 'req' => ['items_indicator' => 'bubble'], ), 'bubble_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} [pagelayer-icon="bubble"] .pagelayer-cart-button-icon[data-counter]:before' => 'color:{{val}}'], 'show' => ['bubble_colors' => 'normal'], ), 'bubble_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} [pagelayer-icon="bubble"] .pagelayer-cart-button-icon[data-counter]:before' => 'background-color:{{val}}'], 'show' => ['bubble_colors' => 'normal'], ), 'bubble_color_hover' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} [pagelayer-icon="bubble"] .pagelayer-cart-button-icon[data-counter]:hover:before' => 'color:{{val}}'], 'show' => ['bubble_colors' => 'hover'], ), 'bubble_bg_color_hover' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} [pagelayer-icon="bubble"] .pagelayer-cart-button-icon[data-counter]:hover:before' => 'background-color:{{val}}'], 'show' => ['bubble_colors' => 'hover'], ), ), 'container_style' => array( 'container_position' => array( 'type' => 'select', 'label' => __('Position'), 'default' => 'fixed_right', 'list' => array( 'fixed_right' => __('Fixed Right'), 'fixed_left' => __('Fixed Left'), 'dropdown' => __('Dropdown'), ), 'addAttr' => [ '{{element}} .pagelayer-woo-menu-cart-container' => 'pagelayer-container-position="{{container_position}}"'], ), 'container_align' => array( 'type' => 'radio', 'label' => __('Position'), 'default' => 'left', 'list' => array( 'left' => __('Left'), 'right' => __('Right'), ), 'css' => ['{{element}} .pagelayer-menu-cart-container' => '{{val}}:0 !important;'], 'req' => ['container_position' => 'dropdown'], ), 'cart_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .pagelayer-menu-cart-container' => 'color:{{val}}'] ), 'cart_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .pagelayer-menu-cart-container' => 'background-color:{{val}}'] ), 'container_close' => array( 'type' => 'slider', 'label' => __('Close Size'), 'css' => ['{{element}} .pagelayer-menu-cart-close' => 'font-size:{{val}}px;'] ), 'container_width' => array( 'type' => 'slider', 'label' => __('Width'), 'screen' => 1, 'units' => ['px', '%'], 'css' => ['{{element}} .pagelayer-menu-cart-container' => 'width:{{val}};'] ), 'sub_total_label' => array( 'type' => 'heading', 'label' => __('Sub Total'), ), 'sub_total_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-mini-cart__total' => 'color: {{val}}'], ), 'sub_total_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-mini-cart__total' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), ), 'products_style' => array( 'products_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-mini-cart > .kkart-mini-cart-item' => 'color:{{val}}'] ), 'products_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .kkart-mini-cart > .kkart-mini-cart-item' => 'background-color:{{val}}'] ), 'products_list_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'units' => [ 'px', 'em'], 'css' => ['{{element}} .kkart-mini-cart > .kkart-mini-cart-item' => 'padding: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}} !important;'], ), 'img_label' => array( 'type' => 'heading', 'label' => __('Image'), ), 'products_img_width' => array( 'type' => 'slider', 'label' => __('Width'), 'default' => '50px', 'units' => ['px', 'em', '%'], 'css' => ['{{element}} .kkart-mini-cart-item img' => 'width: {{val}}'], ), 'title_label' => array( 'type' => 'heading', 'label' => __('Product Title'), ), 'products_title_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-mini-cart-item a' => 'color: {{val}}'], ), 'products_title_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-mini-cart-item a' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'price_label' => array( 'type' => 'heading', 'label' => __('Product Price'), ), 'products_price_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-mini-cart-item .quantity' => 'color: {{val}}'], ), 'products_price_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-mini-cart-item .quantity' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'remove_label' => array( 'type' => 'heading', 'label' => __('Remove Items'), ), 'remove_icon_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .remove_from_cart_button' => 'color: {{val}} !important'], ), 'remove_icon_size' => array( 'type' => 'slider', 'label' => __('Size'), 'css' => ['{{element}} .remove_from_cart_button' => 'font-size: {{val}}px'], ), ), 'buttons_style' => array( 'button_display' => array( 'type' => 'select', 'label' => __('Display'), 'default' => 'inline', 'list' => array( 'inline' => __('Inline'), 'block' => __('Block'), ), 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'display: {{val}}'], 'addAttr' => ['{{element}} .kkart-mini-cart__buttons' => 'pagelayer-display="{{button_display}}"'], ), 'space_between_btn' => array( 'type' => 'slider', 'label' => __('Space Between'), 'default' => 5, 'css' => [ '{{element}} .kkart-mini-cart__buttons[pagelayer-display="inline"] a' => 'margin-left: {{val}}px', '{{element}} .kkart-mini-cart__buttons[pagelayer-display="block"] a' => 'margin-bottom: {{val}}px' ], ), 'btn_padding' => array( 'type' => 'padding', 'label' => __('Padding'), 'units' => [ 'px', 'em'], 'default' => '5,5,5,5', 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'padding: {{val[0]}} {{val[1]}} {{val[2]}} {{val[3]}} !important;'], ), 'btn_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'css' => [ '{{element}} .kkart-mini-cart__buttons' => 'font-family: {{val[0]}} !important; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;' ], ), 'btn_border_radius' => array( 'type' => 'slider', 'label' => __('Border Radius'), 'units' => [ 'px', 'em'], 'default' => '50', 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'border-radius: {{val}} !important'], ), 'btn_color' => array( 'type' => 'color', 'label' => __('Color'), 'default' => '#ffffff', 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'color: {{val}}'], ), 'btn_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'default' => '#585757', 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'background-color: {{val}}'], ), 'btn_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'border-style: {{val}} !important'], 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], ), 'btn_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#42414f', 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'border-color: {{val}} !important'], 'req' => array( '!btn_border_type' => '' ), ), 'btn_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'screen' => 1, 'css' => ['{{element}} .kkart-mini-cart__buttons a' => 'border-width: {{val[0]}}px {{val[1]}}px {{val[2]}}px {{val[3]}}px !important'], 'req' => [ '!btn_border_type' => '' ], ), ), 'styles' => array( 'mini_cart_style' => __('Mini Cart Style'), 'container_style' => __('Container Style'), 'products_style' => __('Products Style'), 'buttons_style' => __('Buttons Style'), ), ) ); //KKART My Account pagelayer_add_shortcode(PAGELAYER_SC_PREFIX.'_kkart_myaccount_tabs', array( 'name' => __('My Account'), 'group' => 'kkart My Account', 'html' => '
{{tab_holder}}
{{tab_content}}
', 'params' => array( 'vertical' => array( 'type' => 'checkbox', 'label' => __('Vertical Tabs'), 'default' => 'true', ), 'vertical_width' => array( 'type' => 'slider', 'label' => __('Tabs container width'), 'default' => 21, 'min' => 0, 'max' => 70, 'step' => 1, 'screen' => 1, 'css' => ['{{element}}' => 'width:100%; display: -webkit-flex; display: flex;', '{{element}} .kkart-myaccount-tabholder' => '-webkit-flex-basis: {{val}}%; flex-basis:{{val}}%', '{{element}} .kkart-myaccount-tabcontainer' => '-webkit-flex-basis: calc(100% - {{val}}%); flex-basis:calc(100% - {{val}}%)', '{{element}} .kkart-myaccount-tabholder .kkart-tablinks' => 'width: 100%;'], 'req' => array( 'vertical' => 'true', ) ), 'myaccount_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'css' => ['{{element}}' => 'border-style: {{val}}'], ), 'myaccount_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#eeeeee', 'req' => [ '!myaccount_border_type' => '' ], 'css' => ['{{element}}' => 'border-color: {{val}}'], ), 'myaccount_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'default' => '1,1,1,1', 'screen' => 1, 'req' => [ '!myaccount_border_type' => '' ], 'css' => ['{{element}}' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], ), 'myaccount_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'default' => '1,1,1,1', 'screen' => 1, 'req' => [ '!myaccount_border_type' => '' ], 'css' => ['{{element}}' => 'border-top-left-radius: {{val[0]}}px; border-top-right-radius: {{val[1]}}px; border-bottom-right-radius: {{val[2]}}px; border-bottom-left-radius: {{val[3]}}px'], ), ), 'tabs_styles' => [ 'tabs_holder_align' => array( 'type' => 'radio', 'label' => __('Alignment'), 'default' => 'left', 'screen' => 1, 'list' => array( 'left' => __('Left'), 'center' => __('Center'), 'right' => __('Right'), ), 'css' => ['{{element}} .kkart-myaccount-tabholder' => 'text-align:{{val}}'], ), 'tabs_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-myaccount-tabholder .kkart-tablinks' => 'color:{{val}}'], ), 'tabs_bg_color' => array( 'type' => 'color', 'label' => __('Background color'), 'css' => ['{{element}} .kkart-myaccount-tabholder' => 'background-color:{{val}}'], ), 'tabs_active_color' => array( 'type' => 'color', 'label' => __('Active Tab Color'), 'css' => ['{{element}} .kkart-myaccount-tabholder .kkart-tablinks.kkart-active-tab' => 'color:{{val}} !important', '{{element}} .kkart-myaccount-tabholder .kkart-tablinks:hover' => 'color:{{val}}'], ), 'tabs_active_bg_color' => array( 'type' => 'color', 'label' => __('Active Tab Background Color'), 'css' => ['{{element}} .kkart-myaccount-tabholder .kkart-tablinks.kkart-active-tab'=> 'background-color:{{val}} !important', '{{element}} .kkart-myaccount-tabholder .kkart-tablinks:hover' => 'background-color:{{val}}'], ), 'tab_title_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'screen' => 1, 'css' => ['{{element}} .kkart-myaccount-tabholder .kkart-tablinks' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'tabs_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'default' => '', 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'css' => ['{{element}} .kkart-myaccount-tabholder' => 'border-style: {{val}}'], ), 'tabs_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#eeeeee', 'req' => [ '!tabs_border_type' => '' ], 'css' => ['{{element}} .kkart-myaccount-tabholder' => 'border-color: {{val}}'], ), 'tabs_holder_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'default' => '1,1,1,0', 'screen' => 1, 'req' => [ '!tabs_border_type' => '' ], 'css' => ['{{element}} .kkart-myaccount-tabholder' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], ), 'tabs_holder_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'default' => '1,1,1,1', 'screen' => 1, 'req' => [ '!tabs_border_type' => '' ], 'css' => ['{{element}} .kkart-myaccount-tabholder' => 'border-top-left-radius: {{val[0]}}px; border-top-right-radius: {{val[1]}}px; border-bottom-right-radius: {{val[2]}}px; border-bottom-left-radius: {{val[3]}}px'], ), ], 'content_styles' => [ 'tabs_content_typo' => array( 'type' => 'typography', 'label' => __('Typography'), 'screen' => 1, 'css' => ['{{element}} .kkart-myaccount-tabcontainer *' => 'font-family: {{val[0]}}; font-size: {{val[1]}}px !important; font-style: {{val[2]}} !important; font-weight: {{val[3]}} !important; font-variant: {{val[4]}} !important; text-decoration-line: {{val[5]}} !important; text-decoration-style: {{val[6]}} !important; line-height: {{val[7]}}em !important; text-transform: {{val[8]}} !important; letter-spacing: {{val[9]}}px !important; word-spacing: {{val[10]}}px !important;'], ), 'tabs_content_color' => array( 'type' => 'color', 'label' => __('Color'), 'css' => ['{{element}} .kkart-myaccount-tabcontainer' => 'color:{{val}}'], ), 'tabs_content_bg_color' => array( 'type' => 'color', 'label' => __('Background Color'), 'css' => ['{{element}} .kkart-myaccount-tabcontainer'=> 'background-color:{{val}}'], ), 'tab_padding' => array( 'type' => 'slider', 'label' => __('Tabs Padding Label'), 'min' => 0, 'max' => 50, 'step' => 1, 'screen' => 1, 'css' => ['{{element}} .kkart-myaccount-tabcontainer' => 'padding: {{val}}px;'], ), 'tab_content_border_type' => array( 'type' => 'select', 'label' => __('Border Type'), 'default' => '', 'list' => [ '' => __('None'), 'solid' => __('Solid'), 'double' => __('Double'), 'dotted' => __('Dotted'), 'dashed' => __('Dashed'), 'groove' => __('Groove'), ], 'css' => ['{{element}} .kkart-myaccount-tabcontainer' => 'border-style: {{val}}'], ), 'tab_content_border_color' => array( 'type' => 'color', 'label' => __('Border Color'), 'default' => '#eeeeee', 'req' => [ '!tab_content_border_type' => '' ], 'css' => ['{{element}} .kkart-myaccount-tabcontainer' => 'border-color: {{val}}'], ), 'tab_content_border_width' => array( 'type' => 'padding', 'label' => __('Border Width'), 'default' => '1,1,1,1', 'screen' => 1, 'req' => [ '!tab_content_border_type' => '' ], 'css' => ['{{element}} .kkart-myaccount-tabcontainer' => 'border-top-width: {{val[0]}}px; border-right-width: {{val[1]}}px; border-bottom-width: {{val[2]}}px; border-left-width: {{val[3]}}px'], ), 'tab_content_border_radius' => array( 'type' => 'padding', 'label' => __('Border Radius'), 'default' => '1,1,1,1', 'screen' => 1, 'req' => [ '!tab_content_border_type' => '' ], 'css' => ['{{element}} .kkart-myaccount-tabcontainer' => 'border-top-left-radius: {{val[0]}}px; border-top-right-radius: {{val[1]}}px; border-bottom-right-radius: {{val[2]}}px; border-bottom-left-radius: {{val[3]}}px'], ), ], 'styles' => [ 'tabs_styles' => __('Tabs'), 'content_styles' => __('Content'), ], ) ); PK!SSclass-walker-docs.phpnu[\n"; if ( $args['has_children'] && 0 === $depth ) { $classes = array( 'page_item', 'page-item-' . self::$parent_item->ID ); if ( self::$parent_item_class ) { $classes[] = self::$parent_item_class; } } } /** * Start element. * * @param string $output - output. * @param int $page - page id. * @param integer $depth - depth. * @param array $args - arguments. * @param integer $current_page - current page id. */ public function start_el( &$output, $page, $depth = 0, $args = array(), $current_page = 0 ) { if ( 0 === $depth ) { self::$parent_item = $page; } if ( $page->ID === $current_page ) { self::$parent_item_class = 'current_page_item'; } else { self::$parent_item_class = ''; } // add the number of childrens. $show_number_childrens = isset( $args['pages_with_children'][ $page->ID ] ) && documentor()->get_option( 'sidebar_show_nav_number_of_childs', 'documentor_single', true ); if ( $show_number_childrens ) { $childs = get_pages( array( 'child_of' => $page->ID, 'post_type' => $page->post_type, ) ); $count = count( $childs ); $args['link_after'] = ( isset( $args['link_after'] ) ? $args['link_after'] : '' ) . ' [' . $count . ']'; } $args['link_before'] = ( isset( $args['link_before'] ) ? $args['link_before'] : '' ) . ( !empty( $args['icon'] ) ? ' ' : '' ); parent::start_el( $output, $page, $depth, $args, $current_page ); } } PK!4UZYYclass-export.phpnu[]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i /]*?>/i'; /** * Custom CSS. * * @var string */ public $custom_css = '.documentor-single-feedback, .documentor-search-form, .documentor-search-form-result { display: none; } body { background-color: #fff; }'; /** * Custom JS. * * @var string */ public $custom_js = ''; /** * Max delta. * * @var integer */ public $max_delta = 1; /** * Construct. */ public function __construct() { if ( function_exists( 'domain_mapping_siteurl' ) ) { $this->wp_site_url = domain_mapping_siteurl( get_current_blog_id() ); $this->wp_content_url = str_replace( get_original_url( $this->wp_site_url ), $this->wp_site_url, content_url() ); } else { $this->wp_site_url = site_url(); $this->wp_content_url = content_url(); } $this->wp_content_name = '/' . wp_basename( WP_CONTENT_DIR ); $this->wp_root_url = str_replace( $this->wp_content_name, '', $this->wp_content_url ); $this->wp_root_dir = str_replace( $this->wp_content_name, '', WP_CONTENT_DIR ); $export_folder = 'documentor-export'; $wp_upload_dir = wp_upload_dir(); $this->export_path = $wp_upload_dir['basedir'] . '/' . $export_folder; $this->export_url = $wp_upload_dir['baseurl'] . '/' . $export_folder; } /** * Array with saved URLs. * * @var array */ protected $saved_urls = array(); /** * Save URL. * * @param string $old_url - old URL. * @param string $new_url - new URL. */ public function save_url( $old_url, $new_url ) { $this->saved_urls[ $old_url ] = $new_url; } /** * Get URL. * * @param string $url - url. */ public function get_url( $url ) { return isset( $this->saved_urls[ $url ] ) ? $this->saved_urls[ $url ] : false; } /** * Replace URLs. * * @param string $content - content. */ public function replace_urls( $content ) { foreach ( $this->saved_urls as $old_url => $new_url ) { if ( preg_match( '/\.html$/', $new_url ) ) { $content = str_replace( '"' . $old_url . '"', '"' . $new_url . '"', $content ); $content = str_replace( '\'' . $old_url . '\'', '\'' . $new_url . '\'', $content ); } else { $content = str_replace( $old_url, $new_url, $content ); } } return $content; } /** * Run exporter. * * @param int $doc_id - documenta ID. */ public function run( $doc_id ) { // Turn off PHP output compression. // phpcs:disable $previous = error_reporting( error_reporting() ^ E_WARNING ); ini_set( 'output_buffering', 'off' ); ini_set( 'zlib.output_compression', false ); error_reporting( $previous ); // phpcs:enable if ( $GLOBALS['is_nginx'] ) { // Setting this header instructs Nginx to disable fastcgi_buffering // and disable gzip for this request. header( 'X-Accel-Buffering: no' ); header( 'Content-Encoding: none' ); } // Start the event stream. header( 'Content-Type: text/event-stream' ); // 2KB padding for IE // phpcs:ignore echo ':' . str_repeat( ' ', 2048 ) . "\n\n"; // Time to run the import! set_time_limit( 0 ); // Ensure we're not buffered. wp_ob_end_flush_all(); flush(); // get all pages. $docs = get_pages( array( 'post_type' => 'docs', 'child_of' => $doc_id, 'post_status' => array( 'publish', 'draft' ), 'posts_per_page' => '-1', // phpcs:ignore 'sort_column' => 'menu_order', 'order' => 'ASC', ) ); $docs = $this->build_tree( $docs, $doc_id ); // get main doc. array_unshift( $docs, array( 'id' => $doc_id, 'file_name' => 'index.html', 'permalink' => get_permalink( $doc_id ), ) ); // save urls. foreach ( $docs as $doc ) { $this->save_url( $doc['permalink'], $doc['file_name'] ); } $this->max_delta += count( $docs ); // export folder path. $export_folder_name = get_post_field( 'post_name', $doc_id ); $export_path = trailingslashit( $this->export_path . '/' . $export_folder_name ); // remove export folder. $this->rimraf_dir( $export_path ); // run export. foreach ( $docs as $doc ) { $this->emit_sse_message( $doc['file_name'] ); $this->run_single( $doc['permalink'], $doc['file_name'], $export_path ); } // zip. $this->emit_sse_message( 'ZIP Documentation' ); $result = $this->zip( $doc_id ); $this->emit_sse_message( $result, 'complete' ); } /** * Run single document. * * @param string $permalink - page link. * @param string $file_name - file name. * @param string $export_path - export path. */ public function run_single( $permalink, $file_name, $export_path ) { // request page. $content = wp_remote_get( $permalink ); if ( is_wp_error( $content ) ) { return 'Can\'t get post content.'; } // get page html content. $content = wp_remote_retrieve_body( $content ); // check if html. if ( ( ( stripos( $content, ']*(?:amp|⚡)/', $content ) === 1 || stripos( $content, '#Usmi', $content, $matches ) ) { foreach ( $matches[0] as $tag ) { if ( preg_match( '#]*src=("|\')([^>]*)("|\')#Usmi', $tag, $source ) ) { $url = $this->normalize_url( $source[2] ); $path = $this->get_path( $url ); // copy file. if ( $path && ! $this->get_url( $url ) ) { $relative_path = $this->get_assets_relative_path( $path ); $copy_to = $export_path . '/' . $relative_path; $this->copy_file( $path, $copy_to ); $this->save_url( $url, '.' . $relative_path ); } } } } // parse and save all css files. if ( preg_match_all( '#(]*stylesheet[^>]*>)#Usmi', $content, $matches ) ) { foreach ( $matches[0] as $tag ) { if ( preg_match( '#normalize_url( $source[2] ); $path = $this->get_path( $url ); // copy file. if ( $path && ! $this->get_url( $url ) ) { $relative_path = $this->get_assets_relative_path( $path ); $copy_to = $export_path . '/' . $relative_path; if ( $this->copy_file( $path, $copy_to ) ) { // find imported images, fonts and other files in css content. $this->parse_css( $url, $export_path ); } $this->save_url( $url, '.' . $relative_path ); } } } } // find all links in html. preg_match_all( '#\bhttps?://[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/))#', $content, $matches ); if ( is_array( $matches ) ) { foreach ( $matches[0] as $url ) { $url = $this->normalize_url( $url ); // save images. $url_ext = pathinfo( $url, PATHINFO_EXTENSION ); if ( in_array( $url_ext, $this->img_extensions, true ) && ! $this->get_url( $url ) ) { $path = $this->get_path( $url ); // copy file. if ( $path ) { $relative_path = $this->get_assets_relative_path( $path ); $copy_to = $export_path . '/' . $relative_path; $this->copy_file( $path, $copy_to ); $this->save_url( $url, '.' . $relative_path ); } } } } // replace all document links. $content = $this->replace_urls( $content ); // add custom js and css. $custom_js = documentor()->get_option( 'custom_js', 'documentor_export', $this->custom_js ); if ( $custom_js ) { $content = str_replace( '', "\n\n\n", $content ); } $custom_css = documentor()->get_option( 'custom_css', 'documentor_export', $this->custom_css ); if ( $custom_css ) { if ( false !== stripos( $custom_css, '' ) ) { $custom_css = trim( preg_replace( '#]*>(.*)#is', '$1', $custom_css ) ); } $content = str_replace( '', '\n\n", $content ); } $content = $this->clean_html( $content ); // save html file. $html_path = $export_path . '/' . $file_name; if ( ! file_exists( $html_path ) ) { wp_mkdir_p( pathinfo( $html_path, PATHINFO_DIRNAME ) ); file_put_contents( $html_path, $content, 0644 ); // phpcs:ignore } unset( $content ); return 'Exported'; } /** * Build tree. * * @param array $docs - all documents array. * @param int $parent - parent doc id. * @param string $name_pre - name of parent doc. */ public function build_tree( $docs, $parent = 0, $name_pre = '' ) { $result = array(); if ( ! $docs ) { return $result; } $i = 1; foreach ( $docs as $key => $doc ) { if ( (int) $doc->post_parent === (int) $parent ) { $name_pre_cur = $name_pre . ( $i++ ) . '.'; unset( $docs[ $key ] ); $result[] = array( 'id' => $doc->ID, 'file_name' => $name_pre_cur . $doc->post_name . '.html', 'permalink' => get_permalink( $doc->ID ), ); // get childs. $result = array_merge( $result, $this->build_tree( $docs, $doc->ID, $name_pre_cur ) ); } } return $result; } /** * Parse CSS. * * @param string $css_url - css url. * @param string $export_path - export path. */ public function parse_css( $css_url, $export_path ) { $css_path = $this->get_path( $css_url ); $assets = array(); if ( ! $css_path ) { return; } // get css content and remove comments. // phpcs:ignore $css_content_nocomments = preg_replace( '#/\*.*\*/#Um', '', file_get_contents( $css_path ) ); // find imported files in css content. preg_match_all( "/@import[ ]*['\"]{0,}(url\()*['\"]*([^;'\"\)]*)['\"\)]*/ui", $css_content_nocomments, $matches ); if ( is_array( $matches ) ) { foreach ( $matches[2] as $import ) { $url = $this->normalize_url( $import ); $path = $this->get_path( $url, $css_url ); $assets[] = $path; if ( $path && file_exists( $path ) && is_readable( $path ) ) { $assets[] = $path; // copy CSS file. $relative_path = $this->get_assets_relative_path( $path ); $copy_to = $export_path . '/' . $relative_path; if ( $this->copy_file( $path, $copy_to ) ) { // find imported images, fonts and other files in css content. $this->parse_css( $url, $export_path ); } } } } // find images. preg_match_all( '#(background[^;{}]*url\((?!\s?"?\'?\s?data)(.*)\)[^;}]*)(?:;|$|})#Usm', $css_content_nocomments, $matches ); if ( is_array( $matches ) ) { foreach ( $matches[2] as $count => $url ) { $path = $this->get_path( $url, $css_url ); if ( $path ) { $assets[] = $path; } } } // find fonts. $fonturl_regex = $this->get_fonts_regex(); preg_match_all( $fonturl_regex, $css_content_nocomments, $matches ); if ( is_array( $matches ) ) { foreach ( $matches[0] as $count => $url ) { $path = $this->get_path( $url, $css_url ); if ( $path ) { $assets[] = $path; } } } // copy all assets to destination folder. $assets = array_unique( $assets ); foreach ( $assets as $asset ) { $relative_path = $this->get_assets_relative_path( $asset ); $copy_to = $export_path . '/' . $relative_path; $this->copy_file( $asset, $copy_to ); } unset( $css_content_nocomments ); unset( $assets ); } /** * Get fonts. * * @return string */ public function get_fonts_regex() { // regex to find fonts, externalised to avoid nasty errors for php < 5.3 // http://stackoverflow.com/questions/21392684/extracting-urls-from-font-face-by-searching-within-font-face-for-replacement. return <<<'LOD' ~ (?(DEFINE) (? (["']) (?>[^"'\\]++ | \\{2} | \\. | (?!\g{-1})["'] )*+ \g{-1} ) (? /\* .*? \*/ ) (? (?: https?: | data: ) [^"'\s)}]*+ ) (? (?> [^u}/"']++ | \g | \g | \Bu | u(?!rl\s*+\() | /(?!\*) | \g \g ["']?+ )++ ) (? \G(? url\( \s*+ ["']?+ ) ) \g (*SKIP)(*FAIL) | \g \g?+ \g \K [./]*+ ( [^"'\s)}]*+ ) # url ~xs LOD; } /** * Get path from URL. * * @param string $url - url. * @param boolean $base_url - base url. * @return string */ public function get_path( $url, $base_url = false ) { $url = $this->normalize_url( $url ); // phpcs:ignore $site_host = parse_url( $this->wp_site_url, PHP_URL_HOST ); // normalize. if ( strpos( $url, '//' ) === 0 ) { if ( is_ssl() ) { $url = 'https:' . $url; } else { $url = 'http:' . $url; } } elseif ( ( strpos( $url, '//' ) === false ) && ( strpos( $url, $site_host ) === false ) ) { if ( $this->wp_site_url === $site_host ) { $url = $this->wp_site_url . $url; } elseif ( $base_url && strpos( $url, 'http' ) !== 0 ) { if ( strpos( $url, './' ) === 0 ) { $url = preg_replace( '^/.\//', '', $url ); } $base_url_folder = pathinfo( $base_url, PATHINFO_DIRNAME ); $url = trailingslashit( $base_url_folder ) . $url; } else { $subdir_levels = substr_count( preg_replace( '/https?:\/\//', '', $this->wp_site_url ), '/' ); $url = $this->wp_site_url . str_repeat( '/..', $subdir_levels ) . $url; } } // first check; hostname wp site should be hostname of url. // phpcs:ignore $this_host = @parse_url( $url, PHP_URL_HOST ); if ( $this_host !== $site_host ) { return false; } // try to remove "wp root url" from url while not minding http<>https. $tmp_ao_root = preg_replace( '/https?:/', '', $this->wp_root_url ); $tmp_url = preg_replace( '/https?:/', '', $url ); $path = str_replace( $tmp_ao_root, '', $tmp_url ); // final check; if path starts with :// or //, this is not a URL in the WP context and we have to assume we can't aggregate. if ( preg_match( '#^:?//#', $path ) ) { /** External script/css (adsense, etc) */ return false; } $path = str_replace( '//', '/', $this->wp_root_dir . $path ); return $path; } /** * Get assets relative path. * * @param string $path - path. * @return string */ public function get_assets_relative_path( $path ) { $path = str_replace( $this->wp_root_dir, '', $path ); $path = preg_replace( '/^\/wp-content/', '/assets/', $path ); $path = preg_replace( '/^\/wp-includes/', '/assets/', $path ); $path = str_replace( '//', '/', $path ); return $path; } /** * Copy file. * * @param string $from - from path. * @param string $to - to path. * @return boolean */ public function copy_file( $from, $to ) { if ( ! file_exists( $to ) && file_exists( $from ) ) { wp_mkdir_p( pathinfo( $to, PATHINFO_DIRNAME ) ); // phpcs:ignore @copy( $from, $to ); return true; } return false; } /** * Normalize url. * * @param string $url - url. * @return string */ public function normalize_url( $url ) { $url = trim( $url, " \t\n\r\0\x0B\"'" ); if ( strpos( $url, '%' ) !== false ) { $url = urldecode( $url ); } if ( strpos( $url, '?' ) !== false ) { $url = strtok( $url, '?' ); } return $url; } /** * Clean HTML string. * * @param string $html - html. * @return string */ public function clean_html( $html ) { $regexp_array = explode( "\n", documentor()->get_option( 'clean_html', 'documentor_export', $this->clean_html_regexp ) ); foreach ( $regexp_array as $reg ) { $reg = trim( $reg ); if ( $reg && preg_match( $reg, null ) !== false ) { $html = preg_replace( $reg, '', $html ); } } $html = preg_replace( "/(\r?\n){2,}/", "\n\n", $html ); return $html; } /** * Zip document. * * @param int $main_doc_id - post id. * @return string */ public function zip( $main_doc_id ) { $export_folder_name = get_post_field( 'post_name', $main_doc_id ); $source = $this->export_path . '/' . $export_folder_name . '/'; $destination = $this->export_path . '/' . $export_folder_name . '.zip'; $dest_url = $this->export_url . '/' . $export_folder_name . '.zip'; if ( ! extension_loaded( 'zip' ) || ! file_exists( $source ) ) { return false; } // remove old zip. if ( file_exists( $destination ) ) { unlink( $destination ); // phpcs:ignore } $zip = new ZipArchive(); if ( ! $zip->open( $destination, ZIPARCHIVE::CREATE ) ) { return false; } $source = str_replace( '\\', '/', realpath( $source ) ); if ( is_dir( $source ) === true ) { $files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $source ), RecursiveIteratorIterator::SELF_FIRST ); foreach ( $files as $file ) { $file = str_replace( '\\', '/', $file ); // Ignore "." and ".." folders. if ( in_array( substr( $file, strrpos( $file, '/' ) + 1 ), array( '.', '..' ), true ) ) { continue; } $file = realpath( $file ); if ( is_dir( $file ) === true ) { $zip->addEmptyDir( str_replace( $source . '/', '', $file . '/' ) ); } elseif ( is_file( $file ) === true ) { // phpcs:ignore $zip->addFromString( str_replace( $source . '/', '', $file ), file_get_contents( $file ) ); } } } elseif ( is_file( $source ) === true ) { // phpcs:ignore $zip->addFromString( basename( $source ), file_get_contents( $source ) ); } $zip->close(); return $dest_url; } /** * Remove dir. * * @param string $dir - dir path. * @return boolean */ public function rimraf_dir( $dir ) { $files = array_diff( scandir( $dir ), array( '.', '..' ) ); foreach ( $files as $file ) { ( is_dir( "$dir/$file" ) ) ? $this->rimraf_dir( "$dir/$file" ) : unlink( "$dir/$file" ); // phpcs:ignore } return rmdir( $dir ); // phpcs:ignore } /** * Emit a Server-Sent Events message. * * @param string $message - message. * @param string $action - action. */ protected function emit_sse_message( $message, $action = 'message' ) { $data = array( 'action' => $action, 'message' => $message, 'max_delta' => $this->max_delta, ); echo "event: message\n"; echo 'data: ' . wp_json_encode( $data ) . "\n\n"; // Extra padding. echo ':' . str_repeat( ' ', 2048 ) . "\n\n"; // phpcs:ignore flush(); } } PK!IWclass-suggestion.phpnu[display_name ) { $from = $user->display_name; } if ( $user->user_email ) { $from .= ( $from ? ' <' : '' ) . $user->user_email . ( $from ? '>' : '' ); } } else { $from = esc_html__( 'Anonymous', 'documentor' ); } $data['from'] = $from; $data['ip_address'] = self::get_ip_address(); $data['blogname'] = wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ); // phpcs:ignore $wp_email = 'wordpress@' . preg_replace( '#^www\.#', '', strtolower( $_SERVER['SERVER_NAME'] ) ); $email_to = documentor()->get_option( 'show_feedback_suggestion_email', 'documentor_single', '' ) ? documentor()->get_option( 'show_feedback_suggestion_email', 'documentor_single', '' ) : get_option( 'admin_email' ); // translators: %s - blog name. $subject = sprintf( esc_html__( '[%s] New Doc Suggestion', 'documentor' ), $data['blogname'] ); // Prepare headers. $headers = 'Content-Type: text/html; charset="' . get_option( 'blog_charset' ) . "\"\n"; $headers .= 'From: "' . esc_html( $data['from'] ) . "\" <$wp_email>\n"; $headers .= "Reply-To: \"$wp_email\" <$wp_email>\n"; // Prepare message. $message = self::get_mail_html( $data ); return wp_mail( $email_to, wp_specialchars_decode( $subject ), $message, $headers ); } /** * Get mail HTML template. * * @param array $attributes - From block attributes. * * @return string */ public static function get_mail_html( $attributes ) { ob_start(); documentor()->get_template_part( 'feedback-mail', array( 'data' => $attributes, ) ); return ob_get_clean(); } /** * Get a clients IP address * * @return string */ public static function get_ip_address() { $ipaddress = ''; // phpcs:disable if ( isset( $_SERVER['HTTP_CLIENT_IP'] ) ) { $ipaddress = $_SERVER['HTTP_CLIENT_IP']; } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { $ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR']; } elseif ( isset( $_SERVER['HTTP_X_FORWARDED'] ) ) { $ipaddress = $_SERVER['HTTP_X_FORWARDED']; } elseif ( isset( $_SERVER['HTTP_FORWARDED_FOR'] ) ) { $ipaddress = $_SERVER['HTTP_FORWARDED_FOR']; } elseif ( isset( $_SERVER['HTTP_FORWARDED'] ) ) { $ipaddress = $_SERVER['HTTP_FORWARDED']; } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { $ipaddress = $_SERVER['REMOTE_ADDR']; } else { $ipaddress = 'UNKNOWN'; } // phpcs:enable return $ipaddress; } /** * Mail before send. */ public static function mail_before_send() { add_filter( 'wp_mail_content_type', array( __CLASS__, 'get_content_type' ) ); } /** * Mail after send. */ public static function mail_after_send() { remove_filter( 'wp_mail_content_type', array( __CLASS__, 'get_content_type' ) ); } /** * Change wp_mail content type to HTML. * * @return string */ public static function get_content_type() { return 'text/html'; } } PK! Xffclass-settings-api.phpnu[settings_sections = $sections; return $this; } /** * Add a single section * * @param array $section */ function add_section( $section ) { $this->settings_sections[] = $section; return $this; } /** * Set settings fields * * @param array $fields settings fields array */ function set_fields( $fields ) { $this->settings_fields = $fields; return $this; } function add_field( $section, $field ) { $defaults = array( 'name' => '', 'label' => '', 'desc' => '', 'type' => 'text', ); $arg = wp_parse_args( $field, $defaults ); $this->settings_fields[ $section ][] = $arg; return $this; } /** * Initialize and registers the settings sections and fileds to WordPress * * Usually this should be called at `admin_init` hook. * * This function gets the initiated settings sections and fields. Then * registers them to WordPress and ready for use. */ function admin_init() { // register settings sections foreach ( $this->settings_sections as $section ) { if ( false == get_option( $section['id'] ) ) { add_option( $section['id'] ); } if ( isset( $section['desc'] ) && ! empty( $section['desc'] ) ) { $section['desc'] = '
' . $section['desc'] . '
'; $callback = create_function( '', 'echo "' . str_replace( '"', '\"', $section['desc'] ) . '";' ); } else if ( isset( $section['callback'] ) ) { $callback = $section['callback']; } else { $callback = null; } add_settings_section( $section['id'], $section['title'], $callback, $section['id'] ); } // register settings fields foreach ( $this->settings_fields as $section => $field ) { foreach ( $field as $option ) { $name = $option['name']; $type = isset( $option['type'] ) ? $option['type'] : 'text'; $label = isset( $option['label'] ) ? $option['label'] : ''; $callback = isset( $option['callback'] ) ? $option['callback'] : array( $this, 'callback_' . $type ); $args = array( 'id' => $name, 'class' => isset( $option['class'] ) ? $option['class'] : $name, 'label_for' => "{$section}[{$name}]", 'desc' => isset( $option['desc'] ) ? $option['desc'] : '', 'name' => $label, 'section' => $section, 'size' => isset( $option['size'] ) ? $option['size'] : null, 'options' => isset( $option['options'] ) ? $option['options'] : '', 'std' => isset( $option['default'] ) ? $option['default'] : '', 'sanitize_callback' => isset( $option['sanitize_callback'] ) ? $option['sanitize_callback'] : '', 'type' => $type, 'placeholder' => isset( $option['placeholder'] ) ? $option['placeholder'] : '', 'min' => isset( $option['min'] ) ? $option['min'] : '', 'max' => isset( $option['max'] ) ? $option['max'] : '', 'step' => isset( $option['step'] ) ? $option['step'] : '', ); add_settings_field( "{$section}[{$name}]", $label, $callback, $section, $section, $args ); } } // creates our settings in the options table foreach ( $this->settings_sections as $section ) { register_setting( $section['id'], $section['id'], array( $this, 'sanitize_options' ) ); } } /** * Get field description for display * * @param array $args settings field args */ public function get_field_description( $args ) { if ( ! empty( $args['desc'] ) ) { $desc = sprintf( '

%s

', $args['desc'] ); } else { $desc = ''; } return $desc; } /** * Displays a text field for a settings field * * @param array $args settings field args */ function callback_text( $args ) { $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular'; $type = isset( $args['type'] ) ? $args['type'] : 'text'; $placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"'; $html = sprintf( '', $type, $size, $args['section'], $args['id'], $value, $placeholder ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a text field for a settings field * * @param array $args settings field args */ function callback_submit( $args ) { $class = isset( $args['class'] ) ? $args['class'] : 'documentor_button'; $value = isset( $args['placeholder'] ) ? $args['placeholder'] : 'Submit'; $type = isset( $args['type'] ) ? $args['type'] : 'submit'; $placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"'; $html = sprintf( '', $args['section'], $args['id'], $placeholder, $value, $class ); $html .= ''; $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a url field for a settings field * * @param array $args settings field args */ function callback_url( $args ) { $this->callback_text( $args ); } /** * Displays a number field for a settings field * * @param array $args settings field args */ function callback_number( $args ) { $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular'; $type = isset( $args['type'] ) ? $args['type'] : 'number'; $placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"'; $min = empty( $args['min'] ) ? '' : ' min="' . $args['min'] . '"'; $max = empty( $args['max'] ) ? '' : ' max="' . $args['max'] . '"'; $step = empty( $args['max'] ) ? '' : ' step="' . $args['step'] . '"'; $html = sprintf( '', $type, $size, $args['section'], $args['id'], $value, $placeholder, $min, $max, $step ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a checkbox for a settings field * * @param array $args settings field args */ function callback_checkbox( $args ) { $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $html = '
'; $html .= sprintf( '', $args['desc'] ); $html .= '
'; echo $html; } /** * Displays a multicheckbox a settings field * * @param array $args settings field args */ function callback_multicheck( $args ) { $value = $this->get_option( $args['id'], $args['section'], $args['std'] ); $html = '
'; $html .= sprintf( '', $args['section'], $args['id'] ); foreach ( $args['options'] as $key => $label ) { $checked = isset( $value[ $key ] ) ? $value[ $key ] : '0'; $html .= sprintf( '
', $label ); } $html .= $this->get_field_description( $args ); $html .= '
'; echo $html; } /** * Displays a multicheckbox a settings field * * @param array $args settings field args */ function callback_radio( $args ) { $value = $this->get_option( $args['id'], $args['section'], $args['std'] ); $html = '
'; foreach ( $args['options'] as $key => $label ) { $html .= sprintf( '
', $label ); } $html .= $this->get_field_description( $args ); $html .= '
'; echo $html; } /** * Displays a selectbox for a settings field * * @param array $args settings field args */ function callback_select( $args ) { $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular'; $html = sprintf( '' ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a textarea for a settings field * * @param array $args settings field args */ function callback_textarea( $args ) { $value = esc_textarea( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular'; $placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"'; $html = sprintf( '', $size, $args['section'], $args['id'], $placeholder, $value ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a textarea for a settings field * * @param array $args settings field args * @return string */ function callback_html( $args ) { echo $this->get_field_description( $args ); } /** * Displays a rich text textarea for a settings field * * @param array $args settings field args */ function callback_wysiwyg( $args ) { $value = $this->get_option( $args['id'], $args['section'], $args['std'] ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : '500px'; echo '
'; $editor_settings = array( 'teeny' => true, 'textarea_name' => $args['section'] . '[' . $args['id'] . ']', 'textarea_rows' => 10, ); if ( isset( $args['options'] ) && is_array( $args['options'] ) ) { $editor_settings = array_merge( $editor_settings, $args['options'] ); } wp_editor( $value, $args['section'] . '-' . $args['id'], $editor_settings ); echo '
'; echo $this->get_field_description( $args ); } /** * Displays a file upload field for a settings field * * @param array $args settings field args */ function callback_file( $args ) { $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular'; $id = $args['section'] . '[' . $args['id'] . ']'; $label = isset( $args['options']['button_label'] ) ? $args['options']['button_label'] : __( 'Choose File' ); $html = sprintf( '', $size, $args['section'], $args['id'], $value ); $html .= ''; $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a password field for a settings field * * @param array $args settings field args */ function callback_password( $args ) { $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular'; $html = sprintf( '', $size, $args['section'], $args['id'], $value ); $html .= $this->get_field_description( $args ); echo $html; } /** * Displays a color picker field for a settings field * * @param array $args settings field args */ function callback_color( $args ) { $value = esc_attr( $this->get_option( $args['id'], $args['section'], $args['std'] ) ); $size = isset( $args['size'] ) && ! is_null( $args['size'] ) ? $args['size'] : 'regular'; $html = sprintf( '', $size, $args['section'], $args['id'], $value, $args['std'] ); $html .= $this->get_field_description( $args ); echo $html; } /** * Sanitize callback for Settings API * * @return mixed */ function sanitize_options( $options ) { if ( ! $options ) { return $options; } foreach ( $options as $option_slug => $option_value ) { $sanitize_callback = $this->get_sanitize_callback( $option_slug ); // If callback is set, call it if ( $sanitize_callback ) { $options[ $option_slug ] = call_user_func( $sanitize_callback, $option_value ); continue; } } return $options; } /** * Get sanitization callback for given option slug * * @param string $slug option slug * * @return mixed string or bool false */ function get_sanitize_callback( $slug = '' ) { if ( empty( $slug ) ) { return false; } // Iterate over registered fields and see if we can find proper callback foreach ( $this->settings_fields as $section => $options ) { foreach ( $options as $option ) { if ( $option['name'] != $slug ) { continue; } // Return the callback name return isset( $option['sanitize_callback'] ) && is_callable( $option['sanitize_callback'] ) ? $option['sanitize_callback'] : false; } } return false; } /** * Get the value of a settings field * * @param string $option settings field name * @param string $section the section name this field belongs to * @param string $default default text if it's not found * @return string */ function get_option( $option, $section, $default = '' ) { $options = get_option( $section ); if ( isset( $options[ $option ] ) ) { return $options[ $option ]; } return $default; } /** * Show navigations as tab * * Shows all the settings section labels as tab */ function show_navigation() { $html = ''; echo $html; } /** * Show the section settings forms * * This function displays every sections in a different form */ function show_forms() { ?>
settings_sections as $form ) { ?>
script(); } /** * Tabbable JavaScript codes & Initiate Color Picker * * This code uses localstorage for displaying active tabs */ function script() { ?> _style_fix(); } function _style_fix() { global $wp_version; if ( version_compare( $wp_version, '3.8', '<=' ) ) : ?> post_type !== 'docs' ) { return; } ?>
__( 'Votes', 'documentor' ) ); // insert before last element, date. // remove first 3 items and store to $first_items, date remains to $columns. $first_items = array_splice( $columns, 0, 3 ); $new_columns = array_merge( $first_items, $vote, $columns ); return $new_columns; } /** * Make votes column sortable. * * @param array $columns current docs list columns. * * @return array */ public function docs_sortable_columns( $columns ) { $columns['votes'] = array( 'votes', true ); return $columns; } /** * Undocumented function * * @param string $column_name - column name. * @param int $post_id - post id. */ public function docs_list_columns_row( $column_name, $post_id ) { if ( 'votes' === $column_name ) { $positive = get_post_meta( $post_id, 'positive', true ); $negative = get_post_meta( $post_id, 'negative', true ); printf( '%d/%d', esc_html( $positive ), esc_html( $negative ) ); } } /** * Add request filter. */ public function edit_docs_load() { add_filter( 'request', array( $this, 'sort_docs' ) ); } /** * Sort the docs. * * @param array $vars - sort variables. * @return array */ public function sort_docs( $vars ) { // Check if we're viewing the 'docs' post type. if ( isset( $vars['post_type'] ) && 'docs' === $vars['post_type'] ) { // Check if 'orderby' is set to 'votes'. if ( isset( $vars['orderby'] ) && 'votes' === $vars['orderby'] ) { $vars = array_merge( $vars, array( // phpcs:ignore 'meta_key' => 'positive', 'orderby' => 'meta_value_num', ) ); } } return $vars; } } PK!88admin/template-vue.phpnu[

{{ cat.name }}

' . esc_html__( 'create one', 'documentor' ) . '' ); ?>
PK!7admin/class-admin.phpnu[include_dependencies(); $this->init_actions(); $this->init_classes(); } /** * Include dependencies. */ public function include_dependencies() { require_once documentor()->plugin_path . 'includes/class-settings-api.php'; require_once documentor()->plugin_path . 'includes/admin/class-settings.php'; require_once documentor()->plugin_path . 'includes/admin/class-docs-list-table.php'; } /** * Initialize action hooks * * @return void */ public function init_actions() { add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) ); add_action( 'admin_menu', array( $this, 'admin_menu' ) ); add_filter( 'parent_file', array( $this, 'menu_highlight' ) ); add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 ); add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 ); } /** * Initialize classes. */ public function init_classes() { new Documentor_Settings(); new Documentor_Docs_List_Table(); } /** * Load admin scripts and styles * * @param string $hook - hook name. */ public function admin_scripts( $hook ) { if ( 'toplevel_page_documentor' !== $hook ) { wp_enqueue_style( 'documentor-admin-setting', documentor()->plugin_url . 'assets/admin/css/settings_style.css', array(), '1.0.0' ); return; } wp_enqueue_script( 'vuejs', documentor()->plugin_url . 'assets/vendor/vue/vue.min.js', array(), '2.5.13', true ); wp_enqueue_script( 'sweetalert', documentor()->plugin_url . 'assets/vendor/sweetalert/js/sweetalert.min.js', array( 'jquery' ), '1.1.3', true ); wp_enqueue_script( 'documentor-admin', documentor()->plugin_url . 'assets/admin/js/script.min.js', array( 'jquery', 'jquery-ui-sortable', 'wp-util' ), '1.0.0', true ); wp_localize_script( 'documentor-admin', 'documentor_admin_vars', array( 'nonce' => wp_create_nonce( 'documentor-admin-nonce' ), 'editurl' => home_url( '/?pagelayer-live=1&p=' ), 'viewurl' => home_url( '/?p=' ), '__' => array( 'enter_doc_title' => __( 'Enter doc title', 'documentor' ), 'enter_section_title' => __( 'Enter section title', 'documentor' ), // translators: %s - copy. 'clone_default_title' => __( '%s Copy', 'documentor' ), 'remove_doc_title' => __( 'Are you sure?', 'documentor' ), 'remove_doc_text' => __( 'Are you sure to delete the entire documentation? Sections and articles inside this doc will be deleted too!', 'documentor' ), 'remove_doc_button_yes' => __( 'Yes, delete it!', 'documentor' ), 'remove_section_title' => __( 'Are you sure?', 'documentor' ), 'remove_section_text' => __( 'Are you sure to delete the entire section? Articles inside this section will be deleted too!', 'documentor' ), 'remove_section_button_yes' => __( 'Yes, delete it!', 'documentor' ), 'remove_article_title' => __( 'Are you sure?', 'documentor' ), 'remove_article_text' => __( 'Are you sure to delete the article?', 'documentor' ), 'remove_article_button_yes' => __( 'Yes, delete it!', 'documentor' ), 'post_deleted_text' => __( 'This post has been deleted', 'documentor' ), 'export_doc_text' => __( 'This process may take a while depending on your documentation size.', 'documentor' ), // translators: %s - export. 'export_doc_title' => __( 'Export %s?', 'documentor' ), 'export_doc_button_yes' => __( 'Export!', 'documentor' ), 'exporting_doc_title' => __( 'Exporting...', 'documentor' ), 'exporting_doc_text' => __( 'Starting', 'documentor' ), 'exported_doc_title' => __( 'Successfully Exported', 'documentor' ), 'exported_doc_download' => __( 'Download ZIP', 'documentor' ), 'exported_doc_cancel' => __( 'Close', 'documentor' ), ), ) ); wp_enqueue_style( 'sweetalert', documentor()->plugin_url . 'assets/vendor/sweetalert/css/sweetalert.css', array(), '1.1.3' ); wp_enqueue_style( 'documentor-admin', documentor()->plugin_url . 'assets/admin/css/style.min.css', array(), '1.0.0' ); wp_style_add_data( 'documentor-admin', 'rtl', 'replace' ); wp_style_add_data( 'documentor-admin', 'suffix', '.min' ); } /** * Get the admin menu position * * @return int the position of the menu */ public function get_menu_position() { return apply_filters( 'documentor_menu_position', 48 ); } /** * Add menu items * * @return void */ public function admin_menu() { add_menu_page( __( 'Documentor', 'documentor' ), __( 'Documentor', 'documentor' ), 'publish_posts', 'documentor', array( $this, 'page_index' ), 'dashicons-media-document', $this->get_menu_position() ); add_submenu_page( 'documentor', __( 'Documentations', 'documentor' ), __( 'Documentations', 'documentor' ), 'publish_posts', 'documentor', array( $this, 'page_index' ) ); add_submenu_page( 'documentor', __( 'Categories', 'documentor' ), __( 'Categories', 'documentor' ), 'publish_posts', 'edit-tags.php?taxonomy=docs_category&post_type=docs' ); } /** * Highlight the proper top level menu * * @link http://wordpress.org/support/topic/moving-taxonomy-ui-to-another-main-menu?replies=5#post-2432769 * * @global obj $current_screen * @param string $parent_file - parent file. * * @return string */ public function menu_highlight( $parent_file ) { global $current_screen; if ( 'docs' === $current_screen->post_type ) { $parent_file = 'documentor'; } return $parent_file; } /** * Add a post display state for special Documents in the page list table. * * @param array $post_states An array of post display states. * @param WP_Post $post The current post object. * @return array $post_states An array of post display states. */ public function display_post_states( $post_states, $post ) { $documents_page_id = documentor()->get_option( 'docs_page_id', 'documentor_settings' ); if ( 'page' === $post->post_type && $documents_page_id && intval( $documents_page_id ) === $post->ID ) { $post_states[] = esc_html__( 'Documentor', 'documentor' ); } return $post_states; } /** * UI Page handler * * @return void */ public function page_index() { include dirname( __FILE__ ) . '/template-vue.php'; } /** * Change the admin footer text on docs admin pages * * @param string $footer_text - footer text. * * @return string */ public function admin_footer_text( $footer_text ) { $current_screen = get_current_screen(); $pages = array( 'toplevel_page_documentor', 'edit-docs' ); // Check to make sure we're on a docs admin page. if ( isset( $current_screen->id ) && apply_filters( 'documentor_display_admin_footer_text', in_array( $current_screen->id, $pages, true ) ) ) { $footer_text .= ' ' . __( 'Thank you for using Documentor.', 'documentor' ); // translators: %s - docs page url. $footer_text .= ' ' . sprintf( __( 'Use the classic UI.', 'documentor' ), admin_url( 'edit.php?post_type=docs' ) ); } return $footer_text; } } return new Documentor_Admin(); PK!1//admin/class-settings.phpnu[settings_api = new Documentor_Settings_API(); add_action( 'admin_init', array( $this, 'admin_init' ) ); add_action( 'admin_menu', array( $this, 'admin_menu' ) ); } /** * Initialize the settings */ public function admin_init() { // set the settings. $this->settings_api->set_sections( $this->get_settings_sections() ); $this->settings_api->set_fields( $this->get_settings_fields() ); // initialize settings. $this->settings_api->admin_init(); } /** * Register the admin settings menu */ public function admin_menu() { add_submenu_page( 'documentor', __( 'Documentor Settings', 'documentor' ), __( 'Settings', 'documentor' ), 'manage_options', 'documentor-settings', array( $this, 'plugin_page' ) ); } /** * Plugin settings sections * * @return array */ public function get_settings_sections() { $sections = array( array( 'id' => 'documentor_settings', 'title' => __( 'General', 'documentor' ), ), array( 'id' => 'documentor_single', 'title' => __( 'Single Document', 'documentor' ), ), array( 'id' => 'documentor_archive', 'title' => __( 'Archive', 'documentor' ), ), array( 'id' => 'documentor_export', 'title' => __( 'Export', 'documentor' ), ), array( 'id' => 'documentor_import', 'title' => __( 'Import', 'documentor' ), ), ); return $sections; } /** * Returns all the settings fields * * @return array settings fields */ public function get_settings_fields() { include_once dirname( __FILE__ ) . '/../class-export.php'; $export_class = new Documentor_Export(); $settings_fields = array( 'documentor_settings' => array( array( 'name' => 'docs_page_id', 'label' => __( 'Documentation Archive Page', 'documentor' ), 'desc' => __( 'Page to display documentations list.
If you see the 404 error, please go to Settings > Permalinks and press "Save Changes" button.', 'documentor' ), 'type' => 'select', 'options' => $this->get_pages(), ), ), 'documentor_single' => array( array( 'name' => 'show_comments', 'label' => __( 'Display Comments', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'show_feedback_buttons', 'label' => __( 'Display Feedback Buttons', 'documentor' ), 'desc' => __( 'Helpful feedback', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'show_feedback_buttons_likes', 'desc' => __( 'Display Likes / Dislikes Count', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'show_feedback_suggestion', 'desc' => __( 'Display Suggestion Form After Like', 'documentor' ), 'type' => 'checkbox', 'default' => 'off', ), array( 'name' => 'show_feedback_suggestion_email', 'desc' => __( 'Suggestion Email', 'documentor' ), 'type' => 'text', 'placeholder' => get_option( 'admin_email' ), 'default' => '', ), array( 'name' => 'show_anchor_links', 'label' => __( 'Display Heading Anchors', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'sidebar', 'label' => __( 'Sidebar', 'documentor' ), 'type' => 'html', ), array( 'name' => 'sidebar_show_search', 'label' => __( 'Display Search', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'sidebar_show_nav_parents', 'label' => __( 'Display Parent Links', 'documentor' ), 'type' => 'checkbox', 'default' => 'off', ), array( 'name' => 'sidebar_show_nav_childs', 'label' => __( 'Display Child Links', 'documentor' ), 'desc' => __( 'Always display child navigation links (by default displayed only for active parent doc)', 'documentor' ), 'type' => 'checkbox', 'default' => 'off', ), array( 'name' => 'sidebar_show_nav_number_of_childs', 'label' => __( 'Display Number of Childs', 'documentor' ), 'desc' => __( 'Display in the title of parent link the number of childs', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'ajax', 'label' => __( 'AJAX loading', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'ajax_custom_js', 'label' => __( 'AJAX Custom JS', 'documentor' ), 'desc' => __( 'Run custom JS after document loaded via AJAX', 'documentor' ), 'type' => 'textarea', 'size' => 'large', 'default' => "/*\n * New page content loaded via ajax you can get in variable 'new_page'\n * Example: console.log(new_page);\n */", ), ), 'documentor_archive' => array( array( 'name' => 'show_articles', 'label' => __( 'Display Articles', 'documentor' ), 'desc' => __( 'Top level articles list', 'documentor' ), 'type' => 'checkbox', 'default' => 'on', ), array( 'name' => 'articles_number', 'label' => __( 'Number of Articles', 'documentor' ), 'desc' => __( 'Type -1 to display all available articles', 'documentor' ), 'type' => 'number', 'default' => 3, ), ), 'documentor_export' => array( array( 'name' => 'custom_css', 'label' => __( 'Custom CSS', 'documentor' ), 'desc' => __( 'Added in exported HTML files', 'documentor' ), 'type' => 'textarea', 'size' => 'large', 'default' => $export_class->custom_css, ), array( 'name' => 'custom_js', 'label' => __( 'Custom JS', 'documentor' ), 'desc' => __( 'Added in exported HTML files', 'documentor' ), 'type' => 'textarea', 'size' => 'large', 'default' => $export_class->custom_js, ), array( 'name' => 'clean_html', 'label' => __( 'Clean HTML RegExp', 'documentor' ), 'desc' => __( 'Each regexp on new line (change it only if you understand what you do)', 'documentor' ), 'type' => 'textarea', 'size' => 'large', 'default' => str_replace( '\'', "\\'", $export_class->clean_html_regexp ), ), ), 'documentor_import' => array( array( 'name' => 'single-template', 'label' => __( 'Single Template', 'documentor' ), 'type' => 'checkbox', 'options' => 'off', ), array( 'name' => 'archive-template', 'label' => __( 'Archive Template', 'documentor' ), 'type' => 'checkbox', 'options' => 'off', ), array( 'name' => 'docs_import', 'type' => 'submit', 'placeholder' => 'Import', 'class' => 'documentor_button_import', ), ), ); return $settings_fields; } /** * The plguin page handler * * @return void */ public function plugin_page() { echo '
'; $this->settings_api->show_navigation(); $this->settings_api->show_forms(); $this->scripts(); echo '
'; } /** * Get all the pages * * @return array page names with key value pairs */ public function get_pages() { $pages_options = array( '' => __( '— Select Page —', 'documentor' ) ); $pages = get_pages( array( 'numberposts' => -1, // phpcs:ignore ) ); if ( $pages ) { foreach ( $pages as $page ) { $pages_options[ $page->ID ] = $page->post_title; } } return $pages_options; } /** * Scripts * * @return void */ public function scripts() { ?> array( 'label' => $label, 'check_conditions' => function ( $args = null ) use ($post_type){ return is_shop(); }, 'no_id_section' => 1, // Id select section not required ), ]; $taxonomies = get_object_taxonomies( $post_type, 'objects' ); $post_taxonomies = wp_filter_object_list( $taxonomies, [ 'public' => true, 'show_in_nav_menus' => true, ] ); foreach ( $post_taxonomies as $slug => $object ) { $condition[$label] += [ $object->name => array( 'label' => sprintf( __( '%s' ), $object->label ), 'check_conditions' => function ( $args = null ) use ($object){ $taxonomy = $object->name; $id = (int) $args['id']; if ( 'category' === $taxonomy ) { return is_category( $id ); } if ( 'post_tag' === $taxonomy ) { return is_tag( $id ); } return is_tax( $taxonomy, $id ); }, 'filter_type' => 'taxonomy', 'object_type' => $object->name, ), ]; } $pagelayer->builder['shop_archives_templates'] = $condition; $pagelayer->builder['type']['shop_archive'] = array( 'label' => __('Shop Archive'), 'need_selection' => 'shop_archives', ); $pagelayer->builder['dispay_on']['shop_archives'] = array( 'label' => __('Shop Archives'), 'check_conditions' => function ( $args = null ){ return is_shop(); }, ); // Set Pagelayer template Id add_action('pagelayer_builder_template_redirect', 'kkart_builder_template_redirect'); } // Set template post function kkart_builder_template_redirect(){ global $pagelayer; $shop_archive = pagelayer_builder_try_to_apply('shop_archive'); if(!is_shop() || empty($shop_archive)){ return; } $pagelayer->template_post = $shop_archive; }PK!6'kkclass-kkart-product-simple.phpnu[supports[] = 'ajax_add_to_cart'; parent::__construct( $product ); } /** * Get internal type. * * @return string */ public function get_type() { return 'simple'; } /** * Get the add to url used mainly in loops. * * @return string */ public function add_to_cart_url() { $url = $this->is_purchasable() && $this->is_in_stock() ? remove_query_arg( 'added-to-cart', add_query_arg( array( 'add-to-cart' => $this->get_id(), ), ( function_exists( 'is_feed' ) && is_feed() ) || ( function_exists( 'is_404' ) && is_404() ) ? $this->get_permalink() : '' ) ) : $this->get_permalink(); return apply_filters( 'kkart_product_add_to_cart_url', $url, $this ); } /** * Get the add to cart button text. * * @return string */ public function add_to_cart_text() { $text = $this->is_purchasable() && $this->is_in_stock() ? __( 'Add to cart', 'kkart' ) : __( 'Read more', 'kkart' ); return apply_filters( 'kkart_product_add_to_cart_text', $text, $this ); } /** * Get the add to cart button text description - used in aria tags. * * @since 3.3.0 * @return string */ public function add_to_cart_description() { /* translators: %s: Product title */ $text = $this->is_purchasable() && $this->is_in_stock() ? __( 'Add “%s” to your cart', 'kkart' ) : __( 'Read more about “%s”', 'kkart' ); return apply_filters( 'kkart_product_add_to_cart_description', sprintf( $text, $this->get_name() ), $this ); } } PK!NvG#class-kkart-order-item-shipping.phpnu[ '', 'method_id' => '', 'instance_id' => '', 'total' => 0, 'total_tax' => 0, 'taxes' => array( 'total' => array(), ), ); /** * Calculate item taxes. * * @since 3.2.0 * @param array $calculate_tax_for Location data to get taxes for. Required. * @return bool True if taxes were calculated. */ public function calculate_taxes( $calculate_tax_for = array() ) { if ( ! isset( $calculate_tax_for['country'], $calculate_tax_for['state'], $calculate_tax_for['postcode'], $calculate_tax_for['city'], $calculate_tax_for['tax_class'] ) ) { return false; } if ( kkart_tax_enabled() ) { $tax_rates = KKART_Tax::find_shipping_rates( $calculate_tax_for ); $taxes = KKART_Tax::calc_tax( $this->get_total(), $tax_rates, false ); $this->set_taxes( array( 'total' => $taxes ) ); } else { $this->set_taxes( false ); } do_action( 'kkart_order_item_shipping_after_calculate_taxes', $this, $calculate_tax_for ); return true; } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- */ /** * Set order item name. * * @param string $value Value to set. * @throws KKART_Data_Exception May throw exception if data is invalid. */ public function set_name( $value ) { $this->set_method_title( $value ); } /** * Set method title. * * @param string $value Value to set. * @throws KKART_Data_Exception May throw exception if data is invalid. */ public function set_method_title( $value ) { $this->set_prop( 'name', kkart_clean( $value ) ); $this->set_prop( 'method_title', kkart_clean( $value ) ); } /** * Set shipping method id. * * @param string $value Value to set. * @throws KKART_Data_Exception May throw exception if data is invalid. */ public function set_method_id( $value ) { $this->set_prop( 'method_id', kkart_clean( $value ) ); } /** * Set shipping instance id. * * @param string $value Value to set. * @throws KKART_Data_Exception May throw exception if data is invalid. */ public function set_instance_id( $value ) { $this->set_prop( 'instance_id', kkart_clean( $value ) ); } /** * Set total. * * @param string $value Value to set. * @throws KKART_Data_Exception May throw exception if data is invalid. */ public function set_total( $value ) { $this->set_prop( 'total', kkart_format_decimal( $value ) ); } /** * Set total tax. * * @param string $value Value to set. * @throws KKART_Data_Exception May throw exception if data is invalid. */ protected function set_total_tax( $value ) { $this->set_prop( 'total_tax', kkart_format_decimal( $value ) ); } /** * Set taxes. * * This is an array of tax ID keys with total amount values. * * @param array $raw_tax_data Value to set. * @throws KKART_Data_Exception May throw exception if data is invalid. */ public function set_taxes( $raw_tax_data ) { $raw_tax_data = maybe_unserialize( $raw_tax_data ); $tax_data = array( 'total' => array(), ); if ( isset( $raw_tax_data['total'] ) ) { $tax_data['total'] = array_map( 'kkart_format_decimal', $raw_tax_data['total'] ); } elseif ( ! empty( $raw_tax_data ) && is_array( $raw_tax_data ) ) { // Older versions just used an array. $tax_data['total'] = array_map( 'kkart_format_decimal', $raw_tax_data ); } $this->set_prop( 'taxes', $tax_data ); if ( 'yes' === get_option( 'kkart_tax_round_at_subtotal' ) ) { $this->set_total_tax( array_sum( $tax_data['total'] ) ); } else { $this->set_total_tax( array_sum( array_map( 'kkart_round_tax_total', $tax_data['total'] ) ) ); } } /** * Set properties based on passed in shipping rate object. * * @param KKART_Shipping_Rate $shipping_rate Shipping rate to set. */ public function set_shipping_rate( $shipping_rate ) { $this->set_method_title( $shipping_rate->get_label() ); $this->set_method_id( $shipping_rate->get_method_id() ); $this->set_instance_id( $shipping_rate->get_instance_id() ); $this->set_total( $shipping_rate->get_cost() ); $this->set_taxes( $shipping_rate->get_taxes() ); $this->set_meta_data( $shipping_rate->get_meta_data() ); } /* |-------------------------------------------------------------------------- | Getters |-------------------------------------------------------------------------- */ /** * Get order item type. * * @return string */ public function get_type() { return 'shipping'; } /** * Get order item name. * * @param string $context View or edit context. * @return string */ public function get_name( $context = 'view' ) { return $this->get_method_title( $context ); } /** * Get title. * * @param string $context View or edit context. * @return string */ public function get_method_title( $context = 'view' ) { $method_title = $this->get_prop( 'method_title', $context ); if ( 'view' === $context ) { return $method_title ? $method_title : __( 'Shipping', 'kkart' ); } else { return $method_title; } } /** * Get method ID. * * @param string $context View or edit context. * @return string */ public function get_method_id( $context = 'view' ) { return $this->get_prop( 'method_id', $context ); } /** * Get instance ID. * * @param string $context View or edit context. * @return string */ public function get_instance_id( $context = 'view' ) { return $this->get_prop( 'instance_id', $context ); } /** * Get total cost. * * @param string $context View or edit context. * @return string */ public function get_total( $context = 'view' ) { return $this->get_prop( 'total', $context ); } /** * Get total tax. * * @param string $context View or edit context. * @return string */ public function get_total_tax( $context = 'view' ) { return $this->get_prop( 'total_tax', $context ); } /** * Get taxes. * * @param string $context View or edit context. * @return array */ public function get_taxes( $context = 'view' ) { return $this->get_prop( 'taxes', $context ); } /** * Get tax class. * * @param string $context View or edit context. * @return string */ public function get_tax_class( $context = 'view' ) { return get_option( 'kkart_shipping_tax_class' ); } /* |-------------------------------------------------------------------------- | Array Access Methods |-------------------------------------------------------------------------- | | For backwards compatibility with legacy arrays. | */ /** * Offset get: for ArrayAccess/Backwards compatibility. * * @param string $offset Key. * @return mixed */ public function offsetGet( $offset ) { if ( 'cost' === $offset ) { $offset = 'total'; } return parent::offsetGet( $offset ); } /** * Offset set: for ArrayAccess/Backwards compatibility. * * @deprecated 4.4.0 * @param string $offset Key. * @param mixed $value Value to set. */ public function offsetSet( $offset, $value ) { kkart_deprecated_function( 'KKART_Order_Item_Shipping::offsetSet', '4.4.0', '' ); if ( 'cost' === $offset ) { $offset = 'total'; } parent::offsetSet( $offset, $value ); } /** * Offset exists: for ArrayAccess. * * @param string $offset Key. * @return bool */ public function offsetExists( $offset ) { if ( in_array( $offset, array( 'cost' ), true ) ) { return true; } return parent::offsetExists( $offset ); } } PK!A>#5#5class-kkart-privacy-erasers.phpnu[ false, 'items_retained' => false, 'messages' => array(), 'done' => true, ); $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. if ( ! $user instanceof WP_User ) { return $response; } $customer = new KKART_Customer( $user->ID ); if ( ! $customer ) { return $response; } $props_to_erase = apply_filters( 'kkart_privacy_erase_customer_personal_data_props', array( 'billing_first_name' => __( 'Billing First Name', 'kkart' ), 'billing_last_name' => __( 'Billing Last Name', 'kkart' ), 'billing_company' => __( 'Billing Company', 'kkart' ), 'billing_address_1' => __( 'Billing Address 1', 'kkart' ), 'billing_address_2' => __( 'Billing Address 2', 'kkart' ), 'billing_city' => __( 'Billing City', 'kkart' ), 'billing_postcode' => __( 'Billing Postal/Zip Code', 'kkart' ), 'billing_state' => __( 'Billing State', 'kkart' ), 'billing_country' => __( 'Billing Country / Region', 'kkart' ), 'billing_phone' => __( 'Phone Number', 'kkart' ), 'billing_email' => __( 'Email Address', 'kkart' ), 'shipping_first_name' => __( 'Shipping First Name', 'kkart' ), 'shipping_last_name' => __( 'Shipping Last Name', 'kkart' ), 'shipping_company' => __( 'Shipping Company', 'kkart' ), 'shipping_address_1' => __( 'Shipping Address 1', 'kkart' ), 'shipping_address_2' => __( 'Shipping Address 2', 'kkart' ), 'shipping_city' => __( 'Shipping City', 'kkart' ), 'shipping_postcode' => __( 'Shipping Postal/Zip Code', 'kkart' ), 'shipping_state' => __( 'Shipping State', 'kkart' ), 'shipping_country' => __( 'Shipping Country / Region', 'kkart' ), ), $customer ); foreach ( $props_to_erase as $prop => $label ) { $erased = false; if ( is_callable( array( $customer, 'get_' . $prop ) ) && is_callable( array( $customer, 'set_' . $prop ) ) ) { $value = $customer->{"get_$prop"}( 'edit' ); if ( $value ) { $customer->{"set_$prop"}( '' ); $erased = true; } } $erased = apply_filters( 'kkart_privacy_erase_customer_personal_data_prop', $erased, $prop, $customer ); if ( $erased ) { /* Translators: %s Prop name. */ $response['messages'][] = sprintf( __( 'Removed customer "%s"', 'kkart' ), $label ); $response['items_removed'] = true; } } $customer->save(); /** * Allow extensions to remove data for this customer and adjust the response. * * @since 3.4.0 * @param array $response Array resonse data. Must include messages, num_items_removed, num_items_retained, done. * @param KKART_Order $order A customer object. */ return apply_filters( 'kkart_privacy_erase_personal_data_customer', $response, $customer ); } /** * Finds and erases data which could be used to identify a person from Kkart data assocated with an email address. * * Orders are erased in blocks of 10 to avoid timeouts. * * @since 3.4.0 * @param string $email_address The user email address. * @param int $page Page. * @return array An array of personal data in name value pairs */ public static function order_data_eraser( $email_address, $page ) { $page = (int) $page; $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. $erasure_enabled = kkart_string_to_bool( get_option( 'kkart_erasure_request_removes_order_data', 'no' ) ); $response = array( 'items_removed' => false, 'items_retained' => false, 'messages' => array(), 'done' => true, ); $order_query = array( 'limit' => 10, 'page' => $page, 'customer' => array( $email_address ), ); if ( $user instanceof WP_User ) { $order_query['customer'][] = (int) $user->ID; } $orders = kkart_get_orders( $order_query ); if ( 0 < count( $orders ) ) { foreach ( $orders as $order ) { if ( apply_filters( 'kkart_privacy_erase_order_personal_data', $erasure_enabled, $order ) ) { self::remove_order_personal_data( $order ); /* Translators: %s Order number. */ $response['messages'][] = sprintf( __( 'Removed personal data from order %s.', 'kkart' ), $order->get_order_number() ); $response['items_removed'] = true; } else { /* Translators: %s Order number. */ $response['messages'][] = sprintf( __( 'Personal data within order %s has been retained.', 'kkart' ), $order->get_order_number() ); $response['items_retained'] = true; } } $response['done'] = 10 > count( $orders ); } else { $response['done'] = true; } return $response; } /** * Finds and removes customer download logs by email address. * * @since 3.4.0 * @param string $email_address The user email address. * @param int $page Page. * @return array An array of personal data in name value pairs */ public static function download_data_eraser( $email_address, $page ) { $page = (int) $page; $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. $erasure_enabled = kkart_string_to_bool( get_option( 'kkart_erasure_request_removes_download_data', 'no' ) ); $response = array( 'items_removed' => false, 'items_retained' => false, 'messages' => array(), 'done' => true, ); $downloads_query = array( 'limit' => -1, 'page' => $page, 'return' => 'ids', ); if ( $user instanceof WP_User ) { $downloads_query['user_id'] = (int) $user->ID; } else { $downloads_query['user_email'] = $email_address; } $customer_download_data_store = KKART_Data_Store::load( 'customer-download' ); // Revoke download permissions. if ( apply_filters( 'kkart_privacy_erase_download_personal_data', $erasure_enabled, $email_address ) ) { if ( $user instanceof WP_User ) { $result = $customer_download_data_store->delete_by_user_id( (int) $user->ID ); } else { $result = $customer_download_data_store->delete_by_user_email( $email_address ); } if ( $result ) { $response['messages'][] = __( 'Removed access to downloadable files.', 'kkart' ); $response['items_removed'] = true; } } else { $response['messages'][] = __( 'Customer download permissions have been retained.', 'kkart' ); $response['items_retained'] = true; } return $response; } /** * Remove personal data specific to Kkart from an order object. * * Note; this will hinder order processing for obvious reasons! * * @param KKART_Order $order Order object. */ public static function remove_order_personal_data( $order ) { $anonymized_data = array(); /** * Allow extensions to remove their own personal data for this order first, so order data is still available. * * @since 3.4.0 * @param KKART_Order $order A customer object. */ do_action( 'kkart_privacy_before_remove_order_personal_data', $order ); /** * Expose props and data types we'll be anonymizing. * * @since 3.4.0 * @param array $props Keys are the prop names, values are the data type we'll be passing to wp_privacy_anonymize_data(). * @param KKART_Order $order A customer object. */ $props_to_remove = apply_filters( 'kkart_privacy_remove_order_personal_data_props', array( 'customer_ip_address' => 'ip', 'customer_user_agent' => 'text', 'billing_first_name' => 'text', 'billing_last_name' => 'text', 'billing_company' => 'text', 'billing_address_1' => 'text', 'billing_address_2' => 'text', 'billing_city' => 'text', 'billing_postcode' => 'text', 'billing_state' => 'address_state', 'billing_country' => 'address_country', 'billing_phone' => 'phone', 'billing_email' => 'email', 'shipping_first_name' => 'text', 'shipping_last_name' => 'text', 'shipping_company' => 'text', 'shipping_address_1' => 'text', 'shipping_address_2' => 'text', 'shipping_city' => 'text', 'shipping_postcode' => 'text', 'shipping_state' => 'address_state', 'shipping_country' => 'address_country', 'customer_id' => 'numeric_id', 'transaction_id' => 'numeric_id', ), $order ); if ( ! empty( $props_to_remove ) && is_array( $props_to_remove ) ) { foreach ( $props_to_remove as $prop => $data_type ) { // Get the current value in edit context. $value = $order->{"get_$prop"}( 'edit' ); // If the value is empty, it does not need to be anonymized. if ( empty( $value ) || empty( $data_type ) ) { continue; } $anon_value = function_exists( 'wp_privacy_anonymize_data' ) ? wp_privacy_anonymize_data( $data_type, $value ) : ''; /** * Expose a way to control the anonymized value of a prop via 3rd party code. * * @since 3.4.0 * @param string $anon_value Value of this prop after anonymization. * @param string $prop Name of the prop being removed. * @param string $value Current value of the data. * @param string $data_type Type of data. * @param KKART_Order $order An order object. */ $anonymized_data[ $prop ] = apply_filters( 'kkart_privacy_remove_order_personal_data_prop_value', $anon_value, $prop, $value, $data_type, $order ); } } // Set all new props and persist the new data to the database. $order->set_props( $anonymized_data ); // Remove meta data. $meta_to_remove = apply_filters( 'kkart_privacy_remove_order_personal_data_meta', array( 'Payer first name' => 'text', 'Payer last name' => 'text', 'Payer PayPal address' => 'email', 'Transaction ID' => 'numeric_id', ) ); if ( ! empty( $meta_to_remove ) && is_array( $meta_to_remove ) ) { foreach ( $meta_to_remove as $meta_key => $data_type ) { $value = $order->get_meta( $meta_key ); // If the value is empty, it does not need to be anonymized. if ( empty( $value ) || empty( $data_type ) ) { continue; } $anon_value = function_exists( 'wp_privacy_anonymize_data' ) ? wp_privacy_anonymize_data( $data_type, $value ) : ''; /** * Expose a way to control the anonymized value of a value via 3rd party code. * * @since 3.4.0 * @param string $anon_value Value of this data after anonymization. * @param string $prop meta_key key being removed. * @param string $value Current value of the data. * @param string $data_type Type of data. * @param KKART_Order $order An order object. */ $anon_value = apply_filters( 'kkart_privacy_remove_order_personal_data_meta_value', $anon_value, $meta_key, $value, $data_type, $order ); if ( $anon_value ) { $order->update_meta_data( $meta_key, $anon_value ); } else { $order->delete_meta_data( $meta_key ); } } } $order->update_meta_data( '_anonymized', 'yes' ); $order->save(); // Delete order notes which can contain PII. $notes = kkart_get_order_notes( array( 'order_id' => $order->get_id(), ) ); foreach ( $notes as $note ) { kkart_delete_order_note( $note->id ); } // Add note that this event occured. $order->add_order_note( __( 'Personal data removed.', 'kkart' ) ); /** * Allow extensions to remove their own personal data for this order. * * @since 3.4.0 * @param KKART_Order $order A customer object. */ do_action( 'kkart_privacy_remove_order_personal_data', $order ); } /** * Finds and erases customer tokens by email address. * * @since 3.4.0 * @param string $email_address The user email address. * @param int $page Page. * @return array An array of personal data in name value pairs */ public static function customer_tokens_eraser( $email_address, $page ) { $response = array( 'items_removed' => false, 'items_retained' => false, 'messages' => array(), 'done' => true, ); $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. if ( ! $user instanceof WP_User ) { return $response; } $tokens = KKART_Payment_Tokens::get_tokens( array( 'user_id' => $user->ID, ) ); if ( empty( $tokens ) ) { return $response; } foreach ( $tokens as $token ) { KKART_Payment_Tokens::delete( $token->get_id() ); /* Translators: %s Prop name. */ $response['messages'][] = sprintf( __( 'Removed payment token "%d"', 'kkart' ), $token->get_id() ); $response['items_removed'] = true; } /** * Allow extensions to remove data for tokens and adjust the response. * * @since 3.4.0 * @param array $response Array resonse data. Must include messages, num_items_removed, num_items_retained, done. * @param array $tokens Array of tokens. */ return apply_filters( 'kkart_privacy_erase_personal_data_tokens', $response, $tokens ); } } PK!,bjj*customizer/class-kkart-shop-customizer.phpnu[add_panel( 'kkart', array( 'priority' => 200, 'capability' => 'manage_kkart', 'theme_supports' => '', 'title' => __( 'Kkart', 'kkart' ), ) ); $this->add_store_notice_section( $wp_customize ); $this->add_product_catalog_section( $wp_customize ); $this->add_product_images_section( $wp_customize ); $this->add_checkout_section( $wp_customize ); } /** * Frontend CSS styles. */ public function add_frontend_scripts() { if ( ! is_customize_preview() || ! is_store_notice_showing() ) { return; } $css = '.kkart-store-notice, p.demo_store { display: block !important; }'; wp_add_inline_style( 'customize-preview', $css ); } /** * CSS styles to improve our form. */ public function add_styles() { ?> __( 'Default sorting (custom ordering + name)', 'kkart' ), 'popularity' => __( 'Popularity (sales)', 'kkart' ), 'rating' => __( 'Average rating', 'kkart' ), 'date' => __( 'Sort by most recent', 'kkart' ), 'price' => __( 'Sort by price (asc)', 'kkart' ), 'price-desc' => __( 'Sort by price (desc)', 'kkart' ), ) ); return array_key_exists( $value, $options ) ? $value : 'menu_order'; } /** * Store notice section. * * @param WP_Customize_Manager $wp_customize Theme Customizer object. */ private function add_store_notice_section( $wp_customize ) { $wp_customize->add_section( 'kkart_store_notice', array( 'title' => __( 'Store Notice', 'kkart' ), 'priority' => 10, 'panel' => 'kkart', ) ); $wp_customize->add_setting( 'kkart_demo_store', array( 'default' => 'no', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'kkart_bool_to_string', 'sanitize_js_callback' => 'kkart_string_to_bool', ) ); $wp_customize->add_setting( 'kkart_demo_store_notice', array( 'default' => __( 'This is a demo store for testing purposes — no orders shall be fulfilled.', 'kkart' ), 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'wp_kses_post', 'transport' => 'postMessage', ) ); $wp_customize->add_control( 'kkart_demo_store_notice', array( 'label' => __( 'Store notice', 'kkart' ), 'description' => __( 'If enabled, this text will be shown site-wide. You can use it to show events or promotions to visitors!', 'kkart' ), 'section' => 'kkart_store_notice', 'settings' => 'kkart_demo_store_notice', 'type' => 'textarea', ) ); $wp_customize->add_control( 'kkart_demo_store', array( 'label' => __( 'Enable store notice', 'kkart' ), 'section' => 'kkart_store_notice', 'settings' => 'kkart_demo_store', 'type' => 'checkbox', ) ); if ( isset( $wp_customize->selective_refresh ) ) { $wp_customize->selective_refresh->add_partial( 'kkart_demo_store_notice', array( 'selector' => '.kkart-store-notice', 'container_inclusive' => true, 'render_callback' => 'kkart_demo_store', ) ); } } /** * Product catalog section. * * @param WP_Customize_Manager $wp_customize Theme Customizer object. */ public function add_product_catalog_section( $wp_customize ) { $wp_customize->add_section( 'kkart_product_catalog', array( 'title' => __( 'Product Catalog', 'kkart' ), 'priority' => 10, 'panel' => 'kkart', ) ); $wp_customize->add_setting( 'kkart_shop_page_display', array( 'default' => '', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => array( $this, 'sanitize_archive_display' ), ) ); $wp_customize->add_control( 'kkart_shop_page_display', array( 'label' => __( 'Shop page display', 'kkart' ), 'description' => __( 'Choose what to display on the main shop page.', 'kkart' ), 'section' => 'kkart_product_catalog', 'settings' => 'kkart_shop_page_display', 'type' => 'select', 'choices' => array( '' => __( 'Show products', 'kkart' ), 'subcategories' => __( 'Show categories', 'kkart' ), 'both' => __( 'Show categories & products', 'kkart' ), ), ) ); $wp_customize->add_setting( 'kkart_category_archive_display', array( 'default' => '', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => array( $this, 'sanitize_archive_display' ), ) ); $wp_customize->add_control( 'kkart_category_archive_display', array( 'label' => __( 'Category display', 'kkart' ), 'description' => __( 'Choose what to display on product category pages.', 'kkart' ), 'section' => 'kkart_product_catalog', 'settings' => 'kkart_category_archive_display', 'type' => 'select', 'choices' => array( '' => __( 'Show products', 'kkart' ), 'subcategories' => __( 'Show subcategories', 'kkart' ), 'both' => __( 'Show subcategories & products', 'kkart' ), ), ) ); $wp_customize->add_setting( 'kkart_default_catalog_orderby', array( 'default' => 'menu_order', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => array( $this, 'sanitize_default_catalog_orderby' ), ) ); $wp_customize->add_control( 'kkart_default_catalog_orderby', array( 'label' => __( 'Default product sorting', 'kkart' ), 'description' => __( 'How should products be sorted in the catalog by default?', 'kkart' ), 'section' => 'kkart_product_catalog', 'settings' => 'kkart_default_catalog_orderby', 'type' => 'select', 'choices' => apply_filters( 'kkart_default_catalog_orderby_options', array( 'menu_order' => __( 'Default sorting (custom ordering + name)', 'kkart' ), 'popularity' => __( 'Popularity (sales)', 'kkart' ), 'rating' => __( 'Average rating', 'kkart' ), 'date' => __( 'Sort by most recent', 'kkart' ), 'price' => __( 'Sort by price (asc)', 'kkart' ), 'price-desc' => __( 'Sort by price (desc)', 'kkart' ), ) ), ) ); // The following settings should be hidden if the theme is declaring the values. if ( has_filter( 'loop_shop_columns' ) ) { return; } $wp_customize->add_setting( 'kkart_catalog_columns', array( 'default' => 4, 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'absint', 'sanitize_js_callback' => 'absint', ) ); $wp_customize->add_control( 'kkart_catalog_columns', array( 'label' => __( 'Products per row', 'kkart' ), 'description' => __( 'How many products should be shown per row?', 'kkart' ), 'section' => 'kkart_product_catalog', 'settings' => 'kkart_catalog_columns', 'type' => 'number', 'input_attrs' => array( 'min' => kkart_get_theme_support( 'product_grid::min_columns', 1 ), 'max' => kkart_get_theme_support( 'product_grid::max_columns', '' ), 'step' => 1, ), ) ); // Only add this setting if something else isn't managing the number of products per page. if ( ! has_filter( 'loop_shop_per_page' ) ) { $wp_customize->add_setting( 'kkart_catalog_rows', array( 'default' => 4, 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'absint', 'sanitize_js_callback' => 'absint', ) ); } $wp_customize->add_control( 'kkart_catalog_rows', array( 'label' => __( 'Rows per page', 'kkart' ), 'description' => __( 'How many rows of products should be shown per page?', 'kkart' ), 'section' => 'kkart_product_catalog', 'settings' => 'kkart_catalog_rows', 'type' => 'number', 'input_attrs' => array( 'min' => kkart_get_theme_support( 'product_grid::min_rows', 1 ), 'max' => kkart_get_theme_support( 'product_grid::max_rows', '' ), 'step' => 1, ), ) ); } /** * Product images section. * * @param WP_Customize_Manager $wp_customize Theme Customizer object. */ private function add_product_images_section( $wp_customize ) { if ( class_exists( 'Jetpack' ) && Jetpack::is_module_active( 'photon' ) ) { $regen_description = ''; // Nothing to report; Jetpack will handle magically. } elseif ( apply_filters( 'kkart_background_image_regeneration', true ) && ! is_multisite() ) { $regen_description = __( 'After publishing your changes, new image sizes will be generated automatically.', 'kkart' ); } elseif ( apply_filters( 'kkart_background_image_regeneration', true ) && is_multisite() ) { /* translators: 1: tools URL 2: regen thumbs url */ $regen_description = sprintf( __( 'After publishing your changes, new image sizes may not be shown until you regenerate thumbnails. You can do this from the tools section in Kkart or by using a plugin such as Regenerate Thumbnails.', 'kkart' ), admin_url( 'admin.php?page=kkart-status&tab=tools' ), 'https://en-gb.wordpress.org/plugins/regenerate-thumbnails/' ); } else { /* translators: %s: regen thumbs url */ $regen_description = sprintf( __( 'After publishing your changes, new image sizes may not be shown until you Regenerate Thumbnails.', 'kkart' ), 'https://en-gb.wordpress.org/plugins/regenerate-thumbnails/' ); } $wp_customize->add_section( 'kkart_product_images', array( 'title' => __( 'Product Images', 'kkart' ), 'description' => $regen_description, 'priority' => 20, 'panel' => 'kkart', ) ); if ( ! kkart_get_theme_support( 'single_image_width' ) ) { $wp_customize->add_setting( 'kkart_single_image_width', array( 'default' => 600, 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'absint', 'sanitize_js_callback' => 'absint', ) ); $wp_customize->add_control( 'kkart_single_image_width', array( 'label' => __( 'Main image width', 'kkart' ), 'description' => __( 'Image size used for the main image on single product pages. These images will remain uncropped.', 'kkart' ), 'section' => 'kkart_product_images', 'settings' => 'kkart_single_image_width', 'type' => 'number', 'input_attrs' => array( 'min' => 0, 'step' => 1, ), ) ); } if ( ! kkart_get_theme_support( 'thumbnail_image_width' ) ) { $wp_customize->add_setting( 'kkart_thumbnail_image_width', array( 'default' => 300, 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'absint', 'sanitize_js_callback' => 'absint', ) ); $wp_customize->add_control( 'kkart_thumbnail_image_width', array( 'label' => __( 'Thumbnail width', 'kkart' ), 'description' => __( 'Image size used for products in the catalog.', 'kkart' ), 'section' => 'kkart_product_images', 'settings' => 'kkart_thumbnail_image_width', 'type' => 'number', 'input_attrs' => array( 'min' => 0, 'step' => 1, ), ) ); } include_once KKART_ABSPATH . 'includes/customizer/class-kkart-customizer-control-cropping.php'; $wp_customize->add_setting( 'kkart_thumbnail_cropping', array( 'default' => '1:1', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'kkart_clean', ) ); $wp_customize->add_setting( 'kkart_thumbnail_cropping_custom_width', array( 'default' => '4', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'absint', 'sanitize_js_callback' => 'absint', ) ); $wp_customize->add_setting( 'kkart_thumbnail_cropping_custom_height', array( 'default' => '3', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'absint', 'sanitize_js_callback' => 'absint', ) ); $wp_customize->add_control( new KKART_Customizer_Control_Cropping( $wp_customize, 'kkart_thumbnail_cropping', array( 'section' => 'kkart_product_images', 'settings' => array( 'cropping' => 'kkart_thumbnail_cropping', 'custom_width' => 'kkart_thumbnail_cropping_custom_width', 'custom_height' => 'kkart_thumbnail_cropping_custom_height', ), 'label' => __( 'Thumbnail cropping', 'kkart' ), 'choices' => array( '1:1' => array( 'label' => __( '1:1', 'kkart' ), 'description' => __( 'Images will be cropped into a square', 'kkart' ), ), 'custom' => array( 'label' => __( 'Custom', 'kkart' ), 'description' => __( 'Images will be cropped to a custom aspect ratio', 'kkart' ), ), 'uncropped' => array( 'label' => __( 'Uncropped', 'kkart' ), 'description' => __( 'Images will display using the aspect ratio in which they were uploaded', 'kkart' ), ), ), ) ) ); } /** * Checkout section. * * @param WP_Customize_Manager $wp_customize Theme Customizer object. */ public function add_checkout_section( $wp_customize ) { $wp_customize->add_section( 'kkart_checkout', array( 'title' => __( 'Checkout', 'kkart' ), 'priority' => 20, 'panel' => 'kkart', 'description' => __( 'These options let you change the appearance of the Kkart checkout.', 'kkart' ), ) ); // Checkout field controls. $fields = array( 'company' => __( 'Company name', 'kkart' ), 'address_2' => __( 'Address line 2', 'kkart' ), 'phone' => __( 'Phone', 'kkart' ), ); foreach ( $fields as $field => $label ) { $wp_customize->add_setting( 'kkart_checkout_' . $field . '_field', array( 'default' => 'phone' === $field ? 'required' : 'optional', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => array( $this, 'sanitize_checkout_field_display' ), ) ); $wp_customize->add_control( 'kkart_checkout_' . $field . '_field', array( /* Translators: %s field name. */ 'label' => sprintf( __( '%s field', 'kkart' ), $label ), 'section' => 'kkart_checkout', 'settings' => 'kkart_checkout_' . $field . '_field', 'type' => 'select', 'choices' => array( 'hidden' => __( 'Hidden', 'kkart' ), 'optional' => __( 'Optional', 'kkart' ), 'required' => __( 'Required', 'kkart' ), ), ) ); } // Register settings. $wp_customize->add_setting( 'kkart_checkout_highlight_required_fields', array( 'default' => 'yes', 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'kkart_bool_to_string', 'sanitize_js_callback' => 'kkart_string_to_bool', ) ); $wp_customize->add_setting( 'kkart_checkout_terms_and_conditions_checkbox_text', array( /* translators: %s terms and conditions page name and link */ 'default' => sprintf( __( 'I have read and agree to the website %s', 'kkart' ), '[terms]' ), 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'wp_kses_post', 'transport' => 'postMessage', ) ); $wp_customize->add_setting( 'kkart_checkout_privacy_policy_text', array( /* translators: %s privacy policy page name and link */ 'default' => sprintf( __( 'Your personal data will be used to process your order, support your experience throughout this website, and for other purposes described in our %s.', 'kkart' ), '[privacy_policy]' ), 'type' => 'option', 'capability' => 'manage_kkart', 'sanitize_callback' => 'wp_kses_post', 'transport' => 'postMessage', ) ); // Register controls. $wp_customize->add_control( 'kkart_checkout_highlight_required_fields', array( 'label' => __( 'Highlight required fields with an asterisk', 'kkart' ), 'section' => 'kkart_checkout', 'settings' => 'kkart_checkout_highlight_required_fields', 'type' => 'checkbox', ) ); if ( current_user_can( 'manage_privacy_options' ) ) { $choose_pages = array( 'wp_page_for_privacy_policy' => __( 'Privacy policy', 'kkart' ), 'kkart_terms_page_id' => __( 'Terms and conditions', 'kkart' ), ); } else { $choose_pages = array( 'kkart_terms_page_id' => __( 'Terms and conditions', 'kkart' ), ); } $pages = get_pages( array( 'post_type' => 'page', 'post_status' => 'publish,private,draft', 'child_of' => 0, 'parent' => -1, 'exclude' => array( kkart_get_page_id( 'cart' ), kkart_get_page_id( 'checkout' ), kkart_get_page_id( 'myaccount' ), ), 'sort_order' => 'asc', 'sort_column' => 'post_title', ) ); $page_choices = array( '' => __( 'No page set', 'kkart' ) ) + array_combine( array_map( 'strval', wp_list_pluck( $pages, 'ID' ) ), wp_list_pluck( $pages, 'post_title' ) ); foreach ( $choose_pages as $id => $name ) { $wp_customize->add_setting( $id, array( 'default' => '', 'type' => 'option', 'capability' => 'manage_kkart', ) ); $wp_customize->add_control( $id, array( /* Translators: %s: page name. */ 'label' => sprintf( __( '%s page', 'kkart' ), $name ), 'section' => 'kkart_checkout', 'settings' => $id, 'type' => 'select', 'choices' => $page_choices, ) ); } $wp_customize->add_control( 'kkart_checkout_privacy_policy_text', array( 'label' => __( 'Privacy policy', 'kkart' ), 'description' => __( 'Optionally add some text about your store privacy policy to show during checkout.', 'kkart' ), 'section' => 'kkart_checkout', 'settings' => 'kkart_checkout_privacy_policy_text', 'active_callback' => 'kkart_privacy_policy_page_id', 'type' => 'textarea', ) ); $wp_customize->add_control( 'kkart_checkout_terms_and_conditions_checkbox_text', array( 'label' => __( 'Terms and conditions', 'kkart' ), 'description' => __( 'Optionally add some text for the terms checkbox that customers must accept.', 'kkart' ), 'section' => 'kkart_checkout', 'settings' => 'kkart_checkout_terms_and_conditions_checkbox_text', 'active_callback' => 'kkart_terms_and_conditions_page_id', 'type' => 'text', ) ); if ( isset( $wp_customize->selective_refresh ) ) { $wp_customize->selective_refresh->add_partial( 'kkart_checkout_privacy_policy_text', array( 'selector' => '.kkart-privacy-policy-text', 'container_inclusive' => true, 'render_callback' => 'kkart_checkout_privacy_policy_text', ) ); $wp_customize->selective_refresh->add_partial( 'kkart_checkout_terms_and_conditions_checkbox_text', array( 'selector' => '.kkart-terms-and-conditions-checkbox-text', 'container_inclusive' => false, 'render_callback' => 'kkart_terms_and_conditions_checkbox_text', ) ); } } /** * Sanitize field display. * * @param string $value '', 'subcategories', or 'both'. * @return string */ public function sanitize_checkout_field_display( $value ) { $options = array( 'hidden', 'optional', 'required' ); return in_array( $value, $options, true ) ? $value : ''; } } new KKART_Shop_Customizer(); PK!7[6customizer/class-kkart-customizer-control-cropping.phpnu[choices ) ) { return; } $value = $this->value( 'cropping' ); $custom_width = $this->value( 'custom_width' ); $custom_height = $this->value( 'custom_height' ); ?> label ); ?> description ) ) : ?> description ); ?>
    choices as $key => $radio ) : ?>
  • link( 'cropping' ); ?> /> link( 'custom_width' ); ?> /> : link( 'custom_height' ); ?> />
'', 'name' => '', 'file' => '', ); /** * Returns all data for this object. * * @return array */ public function get_data() { return $this->data; } /** * Get allowed mime types. * * @return array */ public function get_allowed_mime_types() { return apply_filters( 'kkart_downloadable_file_allowed_mime_types', get_allowed_mime_types() ); } /** * Get type of file path set. * * @param string $file_path optional. * @return string absolute, relative, or shortcode. */ public function get_type_of_file_path( $file_path = '' ) { $file_path = $file_path ? $file_path : $this->get_file(); if ( 0 === strpos( $file_path, 'http' ) || 0 === strpos( $file_path, '//' ) ) { return 'absolute'; } elseif ( '[' === substr( $file_path, 0, 1 ) && ']' === substr( $file_path, -1 ) ) { return 'shortcode'; } else { return 'relative'; } } /** * Get file type. * * @return string */ public function get_file_type() { $type = wp_check_filetype( strtok( $this->get_file(), '?' ), $this->get_allowed_mime_types() ); return $type['type']; } /** * Get file extension. * * @return string */ public function get_file_extension() { $parsed_url = wp_parse_url( $this->get_file(), PHP_URL_PATH ); return pathinfo( $parsed_url, PATHINFO_EXTENSION ); } /** * Check if file is allowed. * * @return boolean */ public function is_allowed_filetype() { $file_path = $this->get_file(); // File types for URL-based files located on the server should get validated. $is_file_on_server = false; if ( false !== stripos( $file_path, network_site_url( '/', 'https' ) ) || false !== stripos( $file_path, network_site_url( '/', 'http' ) ) || false !== stripos( $file_path, site_url( '/', 'https' ) ) || false !== stripos( $file_path, site_url( '/', 'http' ) ) ) { $is_file_on_server = true; } if ( ! $is_file_on_server && 'relative' !== $this->get_type_of_file_path() ) { return true; } return ! $this->get_file_extension() || in_array( $this->get_file_type(), $this->get_allowed_mime_types(), true ); } /** * Validate file exists. * * @return boolean */ public function file_exists() { if ( 'relative' !== $this->get_type_of_file_path() ) { return true; } $file_url = $this->get_file(); if ( '..' === substr( $file_url, 0, 2 ) || '/' !== substr( $file_url, 0, 1 ) ) { $file_url = realpath( ABSPATH . $file_url ); } elseif ( substr( WP_CONTENT_DIR, strlen( untrailingslashit( ABSPATH ) ) ) === substr( $file_url, 0, strlen( substr( WP_CONTENT_DIR, strlen( untrailingslashit( ABSPATH ) ) ) ) ) ) { $file_url = realpath( WP_CONTENT_DIR . substr( $file_url, 11 ) ); } return apply_filters( 'kkart_downloadable_file_exists', file_exists( $file_url ), $this->get_file() ); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- */ /** * Set ID. * * @param string $value Download ID. */ public function set_id( $value ) { $this->data['id'] = kkart_clean( $value ); } /** * Set name. * * @param string $value Download name. */ public function set_name( $value ) { $this->data['name'] = kkart_clean( $value ); } /** * Set previous_hash. * * @deprecated 3.3.0 No longer using filename based hashing to keep track of files. * @param string $value Previous hash. */ public function set_previous_hash( $value ) { kkart_deprecated_function( __FUNCTION__, '3.3' ); $this->data['previous_hash'] = kkart_clean( $value ); } /** * Set file. * * @param string $value File URL/Path. */ public function set_file( $value ) { switch ( $this->get_type_of_file_path( $value ) ) { case 'absolute': $this->data['file'] = esc_url_raw( $value ); break; default: $this->data['file'] = kkart_clean( $value ); break; } } /* |-------------------------------------------------------------------------- | Getters |-------------------------------------------------------------------------- */ /** * Get id. * * @return string */ public function get_id() { return $this->data['id']; } /** * Get name. * * @return string */ public function get_name() { return $this->data['name']; } /** * Get previous_hash. * * @deprecated 3.3.0 No longer using filename based hashing to keep track of files. * @return string */ public function get_previous_hash() { kkart_deprecated_function( __FUNCTION__, '3.3' ); return $this->data['previous_hash']; } /** * Get file. * * @return string */ public function get_file() { return $this->data['file']; } /* |-------------------------------------------------------------------------- | ArrayAccess/Backwards compatibility. |-------------------------------------------------------------------------- */ /** * OffsetGet. * * @param string $offset Offset. * @return mixed */ public function offsetGet( $offset ) { switch ( $offset ) { default: if ( is_callable( array( $this, "get_$offset" ) ) ) { return $this->{"get_$offset"}(); } break; } return ''; } /** * OffsetSet. * * @param string $offset Offset. * @param mixed $value Offset value. */ public function offsetSet( $offset, $value ) { switch ( $offset ) { default: if ( is_callable( array( $this, "set_$offset" ) ) ) { return $this->{"set_$offset"}( $value ); } break; } } /** * OffsetUnset. * * @param string $offset Offset. */ public function offsetUnset( $offset ) {} /** * OffsetExists. * * @param string $offset Offset. * @return bool */ public function offsetExists( $offset ) { return in_array( $offset, array_keys( $this->data ), true ); } } PK!]\ \ .widgets/class-kkart-widget-recently-viewed.phpnu[widget_cssclass = 'kkart widget_recently_viewed_products'; $this->widget_description = __( "Display a list of a customer's recently viewed products.", 'kkart' ); $this->widget_id = 'kkart_recently_viewed_products'; $this->widget_name = __( 'Recent Viewed Products', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Recently Viewed Products', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), 'number' => array( 'type' => 'number', 'step' => 1, 'min' => 1, 'max' => 15, 'std' => 10, 'label' => __( 'Number of products to show', 'kkart' ), ), ); parent::__construct(); } /** * Output widget. * * @see WP_Widget * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { $viewed_products = ! empty( $_COOKIE['kkart_recently_viewed'] ) ? (array) explode( '|', wp_unslash( $_COOKIE['kkart_recently_viewed'] ) ) : array(); // @codingStandardsIgnoreLine $viewed_products = array_reverse( array_filter( array_map( 'absint', $viewed_products ) ) ); if ( empty( $viewed_products ) ) { return; } ob_start(); $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : $this->settings['number']['std']; $query_args = array( 'posts_per_page' => $number, 'no_found_rows' => 1, 'post_status' => 'publish', 'post_type' => 'product', 'post__in' => $viewed_products, 'orderby' => 'post__in', ); if ( 'yes' === get_option( 'kkart_hide_out_of_stock_items' ) ) { $query_args['tax_query'] = array( array( 'taxonomy' => 'product_visibility', 'field' => 'name', 'terms' => 'outofstock', 'operator' => 'NOT IN', ), ); // WPCS: slow query ok. } $r = new WP_Query( apply_filters( 'kkart_recently_viewed_products_widget_query_args', $query_args ) ); if ( $r->have_posts() ) { $this->widget_start( $args, $instance ); echo wp_kses_post( apply_filters( 'kkart_before_widget_product_list', '
    ' ) ); $template_args = array( 'widget_id' => isset( $args['widget_id'] ) ? $args['widget_id'] : $this->widget_id, ); while ( $r->have_posts() ) { $r->the_post(); kkart_get_template( 'content-widget-product.php', $template_args ); } echo wp_kses_post( apply_filters( 'kkart_after_widget_product_list', '
' ) ); $this->widget_end( $args ); } wp_reset_postdata(); $content = ob_get_clean(); echo $content; // WPCS: XSS ok. } } PK!^wfCfC*widgets/class-kkart-widget-layered-nav.phpnu[widget_cssclass = 'kkart widget_layered_nav kkart-widget-layered-nav'; $this->widget_description = __( 'Display a list of attributes to filter products in your store.', 'kkart' ); $this->widget_id = 'kkart_layered_nav'; $this->widget_name = __( 'Filter Products by Attribute', 'kkart' ); parent::__construct(); } /** * Updates a particular instance of a widget. * * @see WP_Widget->update * * @param array $new_instance New Instance. * @param array $old_instance Old Instance. * * @return array */ public function update( $new_instance, $old_instance ) { $this->init_settings(); return parent::update( $new_instance, $old_instance ); } /** * Outputs the settings update form. * * @see WP_Widget->form * * @param array $instance Instance. */ public function form( $instance ) { $this->init_settings(); parent::form( $instance ); } /** * Init settings after post types are registered. */ public function init_settings() { $attribute_array = array(); $std_attribute = ''; $attribute_taxonomies = kkart_get_attribute_taxonomies(); if ( ! empty( $attribute_taxonomies ) ) { foreach ( $attribute_taxonomies as $tax ) { if ( taxonomy_exists( kkart_attribute_taxonomy_name( $tax->attribute_name ) ) ) { $attribute_array[ $tax->attribute_name ] = $tax->attribute_name; } } $std_attribute = current( $attribute_array ); } $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Filter by', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), 'attribute' => array( 'type' => 'select', 'std' => $std_attribute, 'label' => __( 'Attribute', 'kkart' ), 'options' => $attribute_array, ), 'display_type' => array( 'type' => 'select', 'std' => 'list', 'label' => __( 'Display type', 'kkart' ), 'options' => array( 'list' => __( 'List', 'kkart' ), 'dropdown' => __( 'Dropdown', 'kkart' ), ), ), 'query_type' => array( 'type' => 'select', 'std' => 'and', 'label' => __( 'Query type', 'kkart' ), 'options' => array( 'and' => __( 'AND', 'kkart' ), 'or' => __( 'OR', 'kkart' ), ), ), ); } /** * Get this widgets taxonomy. * * @param array $instance Array of instance options. * @return string */ protected function get_instance_taxonomy( $instance ) { if ( isset( $instance['attribute'] ) ) { return kkart_attribute_taxonomy_name( $instance['attribute'] ); } $attribute_taxonomies = kkart_get_attribute_taxonomies(); if ( ! empty( $attribute_taxonomies ) ) { foreach ( $attribute_taxonomies as $tax ) { if ( taxonomy_exists( kkart_attribute_taxonomy_name( $tax->attribute_name ) ) ) { return kkart_attribute_taxonomy_name( $tax->attribute_name ); } } } return ''; } /** * Get this widgets query type. * * @param array $instance Array of instance options. * @return string */ protected function get_instance_query_type( $instance ) { return isset( $instance['query_type'] ) ? $instance['query_type'] : 'and'; } /** * Get this widgets display type. * * @param array $instance Array of instance options. * @return string */ protected function get_instance_display_type( $instance ) { return isset( $instance['display_type'] ) ? $instance['display_type'] : 'list'; } /** * Output widget. * * @see WP_Widget * * @param array $args Arguments. * @param array $instance Instance. */ public function widget( $args, $instance ) { if ( ! is_shop() && ! is_product_taxonomy() ) { return; } $_chosen_attributes = KKART_Query::get_layered_nav_chosen_attributes(); $taxonomy = $this->get_instance_taxonomy( $instance ); $query_type = $this->get_instance_query_type( $instance ); $display_type = $this->get_instance_display_type( $instance ); if ( ! taxonomy_exists( $taxonomy ) ) { return; } $terms = get_terms( $taxonomy, array( 'hide_empty' => '1' ) ); if ( 0 === count( $terms ) ) { return; } ob_start(); $this->widget_start( $args, $instance ); if ( 'dropdown' === $display_type ) { wp_enqueue_script( 'selectWoo' ); wp_enqueue_style( 'select2' ); $found = $this->layered_nav_dropdown( $terms, $taxonomy, $query_type ); } else { $found = $this->layered_nav_list( $terms, $taxonomy, $query_type ); } $this->widget_end( $args ); // Force found when option is selected - do not force found on taxonomy attributes. if ( ! is_tax() && is_array( $_chosen_attributes ) && array_key_exists( $taxonomy, $_chosen_attributes ) ) { $found = true; } if ( ! $found ) { ob_end_clean(); } else { echo ob_get_clean(); // @codingStandardsIgnoreLine } } /** * Return the currently viewed taxonomy name. * * @return string */ protected function get_current_taxonomy() { return is_tax() ? get_queried_object()->taxonomy : ''; } /** * Return the currently viewed term ID. * * @return int */ protected function get_current_term_id() { return absint( is_tax() ? get_queried_object()->term_id : 0 ); } /** * Return the currently viewed term slug. * * @return int */ protected function get_current_term_slug() { return absint( is_tax() ? get_queried_object()->slug : 0 ); } /** * Show dropdown layered nav. * * @param array $terms Terms. * @param string $taxonomy Taxonomy. * @param string $query_type Query Type. * @return bool Will nav display? */ protected function layered_nav_dropdown( $terms, $taxonomy, $query_type ) { global $wp; $found = false; if ( $taxonomy !== $this->get_current_taxonomy() ) { $term_counts = $this->get_filtered_term_product_counts( wp_list_pluck( $terms, 'term_id' ), $taxonomy, $query_type ); $_chosen_attributes = KKART_Query::get_layered_nav_chosen_attributes(); $taxonomy_filter_name = kkart_attribute_taxonomy_slug( $taxonomy ); $taxonomy_label = kkart_attribute_label( $taxonomy ); /* translators: %s: taxonomy name */ $any_label = apply_filters( 'kkart_layered_nav_any_label', sprintf( __( 'Any %s', 'kkart' ), $taxonomy_label ), $taxonomy_label, $taxonomy ); $multiple = 'or' === $query_type; $current_values = isset( $_chosen_attributes[ $taxonomy ]['terms'] ) ? $_chosen_attributes[ $taxonomy ]['terms'] : array(); if ( '' === get_option( 'permalink_structure' ) ) { $form_action = remove_query_arg( array( 'page', 'paged' ), add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) ); } else { $form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) ); } echo '
'; echo ''; if ( $multiple ) { echo ''; } if ( 'or' === $query_type ) { echo ''; } echo ''; echo kkart_query_string_form_fields( null, array( 'filter_' . $taxonomy_filter_name, 'query_type_' . $taxonomy_filter_name ), '', true ); // @codingStandardsIgnoreLine echo '
'; kkart_enqueue_js( " // Update value on change. jQuery( '.dropdown_layered_nav_" . esc_js( $taxonomy_filter_name ) . "' ).change( function() { var slug = jQuery( this ).val(); jQuery( ':input[name=\"filter_" . esc_js( $taxonomy_filter_name ) . "\"]' ).val( slug ); // Submit form on change if standard dropdown. if ( ! jQuery( this ).attr( 'multiple' ) ) { jQuery( this ).closest( 'form' ).submit(); } }); // Use Select2 enhancement if possible if ( jQuery().selectWoo ) { var kkart_layered_nav_select = function() { jQuery( '.dropdown_layered_nav_" . esc_js( $taxonomy_filter_name ) . "' ).selectWoo( { placeholder: decodeURIComponent('" . rawurlencode( (string) wp_specialchars_decode( $any_label ) ) . "'), minimumResultsForSearch: 5, width: '100%', allowClear: " . ( $multiple ? 'false' : 'true' ) . ", language: { noResults: function() { return '" . esc_js( _x( 'No matches found', 'enhanced select', 'kkart' ) ) . "'; } } } ); }; kkart_layered_nav_select(); } " ); } return $found; } /** * Count products within certain terms, taking the main WP query into consideration. * * This query allows counts to be generated based on the viewed products, not all products. * * @param array $term_ids Term IDs. * @param string $taxonomy Taxonomy. * @param string $query_type Query Type. * @return array */ protected function get_filtered_term_product_counts( $term_ids, $taxonomy, $query_type ) { global $wpdb; $tax_query = $this->get_main_tax_query(); $meta_query = $this->get_main_meta_query(); if ( 'or' === $query_type ) { foreach ( $tax_query as $key => $query ) { if ( is_array( $query ) && $taxonomy === $query['taxonomy'] ) { unset( $tax_query[ $key ] ); } } } $meta_query = new WP_Meta_Query( $meta_query ); $tax_query = new WP_Tax_Query( $tax_query ); $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' ); $tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' ); $term_ids_sql = '(' . implode( ',', array_map( 'absint', $term_ids ) ) . ')'; // Generate query. $query = array(); $query['select'] = "SELECT COUNT( DISTINCT {$wpdb->posts}.ID ) AS term_count, terms.term_id AS term_count_id"; $query['from'] = "FROM {$wpdb->posts}"; $query['join'] = " INNER JOIN {$wpdb->term_relationships} AS term_relationships ON {$wpdb->posts}.ID = term_relationships.object_id INNER JOIN {$wpdb->term_taxonomy} AS term_taxonomy USING( term_taxonomy_id ) INNER JOIN {$wpdb->terms} AS terms USING( term_id ) " . $tax_query_sql['join'] . $meta_query_sql['join']; $query['where'] = " WHERE {$wpdb->posts}.post_type IN ( 'product' ) AND {$wpdb->posts}.post_status = 'publish' {$tax_query_sql['where']} {$meta_query_sql['where']} AND terms.term_id IN $term_ids_sql"; $search = $this->get_main_search_query_sql(); if ( $search ) { $query['where'] .= ' AND ' . $search; } $query['group_by'] = 'GROUP BY terms.term_id'; $query = apply_filters( 'kkart_get_filtered_term_product_counts_query', $query ); $query_sql = implode( ' ', $query ); // We have a query - let's see if cached results of this query already exist. $query_hash = md5( $query_sql ); // Maybe store a transient of the count values. $cache = apply_filters( 'kkart_layered_nav_count_maybe_cache', true ); if ( true === $cache ) { $cached_counts = (array) get_transient( 'kkart_layered_nav_counts_' . sanitize_title( $taxonomy ) ); } else { $cached_counts = array(); } if ( ! isset( $cached_counts[ $query_hash ] ) ) { // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared $results = $wpdb->get_results( $query_sql, ARRAY_A ); $counts = array_map( 'absint', wp_list_pluck( $results, 'term_count', 'term_count_id' ) ); $cached_counts[ $query_hash ] = $counts; if ( true === $cache ) { set_transient( 'kkart_layered_nav_counts_' . sanitize_title( $taxonomy ), $cached_counts, DAY_IN_SECONDS ); } } return array_map( 'absint', (array) $cached_counts[ $query_hash ] ); } /** * Wrapper for KKART_Query::get_main_tax_query() to ease unit testing. * * @since 4.4.0 * @return array */ protected function get_main_tax_query() { return KKART_Query::get_main_tax_query(); } /** * Wrapper for KKART_Query::get_main_search_query_sql() to ease unit testing. * * @since 4.4.0 * @return string */ protected function get_main_search_query_sql() { return KKART_Query::get_main_search_query_sql(); } /** * Wrapper for KKART_Query::get_main_search_queryget_main_meta_query to ease unit testing. * * @since 4.4.0 * @return array */ protected function get_main_meta_query() { return KKART_Query::get_main_meta_query(); } /** * Show list based layered nav. * * @param array $terms Terms. * @param string $taxonomy Taxonomy. * @param string $query_type Query Type. * @return bool Will nav display? */ protected function layered_nav_list( $terms, $taxonomy, $query_type ) { // List display. echo '
    '; $term_counts = $this->get_filtered_term_product_counts( wp_list_pluck( $terms, 'term_id' ), $taxonomy, $query_type ); $_chosen_attributes = KKART_Query::get_layered_nav_chosen_attributes(); $found = false; $base_link = $this->get_current_page_url(); foreach ( $terms as $term ) { $current_values = isset( $_chosen_attributes[ $taxonomy ]['terms'] ) ? $_chosen_attributes[ $taxonomy ]['terms'] : array(); $option_is_set = in_array( $term->slug, $current_values, true ); $count = isset( $term_counts[ $term->term_id ] ) ? $term_counts[ $term->term_id ] : 0; // Skip the term for the current archive. if ( $this->get_current_term_id() === $term->term_id ) { continue; } // Only show options with count > 0. if ( 0 < $count ) { $found = true; } elseif ( 0 === $count && ! $option_is_set ) { continue; } $filter_name = 'filter_' . kkart_attribute_taxonomy_slug( $taxonomy ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended $current_filter = isset( $_GET[ $filter_name ] ) ? explode( ',', kkart_clean( wp_unslash( $_GET[ $filter_name ] ) ) ) : array(); $current_filter = array_map( 'sanitize_title', $current_filter ); if ( ! in_array( $term->slug, $current_filter, true ) ) { $current_filter[] = $term->slug; } $link = remove_query_arg( $filter_name, $base_link ); // Add current filters to URL. foreach ( $current_filter as $key => $value ) { // Exclude query arg for current term archive term. if ( $value === $this->get_current_term_slug() ) { unset( $current_filter[ $key ] ); } // Exclude self so filter can be unset on click. if ( $option_is_set && $value === $term->slug ) { unset( $current_filter[ $key ] ); } } if ( ! empty( $current_filter ) ) { asort( $current_filter ); $link = add_query_arg( $filter_name, implode( ',', $current_filter ), $link ); // Add Query type Arg to URL. if ( 'or' === $query_type && ! ( 1 === count( $current_filter ) && $option_is_set ) ) { $link = add_query_arg( 'query_type_' . kkart_attribute_taxonomy_slug( $taxonomy ), 'or', $link ); } $link = str_replace( '%2C', ',', $link ); } if ( $count > 0 || $option_is_set ) { $link = apply_filters( 'kkart_layered_nav_link', $link, $term, $taxonomy ); $term_html = '' . esc_html( $term->name ) . ''; } else { $link = false; $term_html = '' . esc_html( $term->name ) . ''; } $term_html .= ' ' . apply_filters( 'kkart_layered_nav_count', '(' . absint( $count ) . ')', $count, $term ); echo '
  • '; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.EscapeOutput.OutputNotEscaped echo apply_filters( 'kkart_layered_nav_term_html', $term_html, $term, $link, $count ); echo '
  • '; } echo '
'; return $found; } } PK!{-widgets/class-kkart-widget-recent-reviews.phpnu[widget_cssclass = 'kkart widget_recent_reviews'; $this->widget_description = __( 'Display a list of recent reviews from your store.', 'kkart' ); $this->widget_id = 'kkart_recent_reviews'; $this->widget_name = __( 'Recent Product Reviews', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Recent reviews', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), 'number' => array( 'type' => 'number', 'step' => 1, 'min' => 1, 'max' => '', 'std' => 10, 'label' => __( 'Number of reviews to show', 'kkart' ), ), ); parent::__construct(); } /** * Output widget. * * @see WP_Widget * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { global $comments, $comment; if ( $this->get_cached_widget( $args ) ) { return; } ob_start(); $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : $this->settings['number']['std']; $comments = get_comments( array( 'number' => $number, 'status' => 'approve', 'post_status' => 'publish', 'post_type' => 'product', 'parent' => 0, ) ); // WPCS: override ok. if ( $comments ) { $this->widget_start( $args, $instance ); echo wp_kses_post( apply_filters( 'kkart_before_widget_product_review_list', '
    ' ) ); foreach ( (array) $comments as $comment ) { kkart_get_template( 'content-widget-reviews.php', array( 'comment' => $comment, 'product' => kkart_get_product( $comment->comment_post_ID ), ) ); } echo wp_kses_post( apply_filters( 'kkart_after_widget_product_review_list', '
' ) ); $this->widget_end( $args ); } $content = ob_get_clean(); echo $content; // WPCS: XSS ok. $this->cache_widget( $args, $content ); } } PK!widget_cssclass = 'kkart widget_rating_filter'; $this->widget_description = __( 'Display a list of star ratings to filter products in your store.', 'kkart' ); $this->widget_id = 'kkart_rating_filter'; $this->widget_name = __( 'Filter Products by Rating', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Average rating', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), ); parent::__construct(); } /** * Count products after other filters have occurred by adjusting the main query. * * @param int $rating Rating. * @return int */ protected function get_filtered_product_count( $rating ) { global $wpdb; $tax_query = KKART_Query::get_main_tax_query(); $meta_query = KKART_Query::get_main_meta_query(); // Unset current rating filter. foreach ( $tax_query as $key => $query ) { if ( ! empty( $query['rating_filter'] ) ) { unset( $tax_query[ $key ] ); break; } } // Set new rating filter. $product_visibility_terms = kkart_get_product_visibility_term_ids(); $tax_query[] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_terms[ 'rated-' . $rating ], 'operator' => 'IN', 'rating_filter' => true, ); $meta_query = new WP_Meta_Query( $meta_query ); $tax_query = new WP_Tax_Query( $tax_query ); $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' ); $tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' ); $sql = "SELECT COUNT( DISTINCT {$wpdb->posts}.ID ) FROM {$wpdb->posts} "; $sql .= $tax_query_sql['join'] . $meta_query_sql['join']; $sql .= " WHERE {$wpdb->posts}.post_type = 'product' AND {$wpdb->posts}.post_status = 'publish' "; $sql .= $tax_query_sql['where'] . $meta_query_sql['where']; $search = KKART_Query::get_main_search_query_sql(); if ( $search ) { $sql .= ' AND ' . $search; } return absint( $wpdb->get_var( $sql ) ); // WPCS: unprepared SQL ok. } /** * Widget function. * * @see WP_Widget * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { if ( ! is_shop() && ! is_product_taxonomy() ) { return; } if ( ! KKART()->query->get_main_query()->post_count ) { return; } ob_start(); $found = false; $rating_filter = isset( $_GET['rating_filter'] ) ? array_filter( array_map( 'absint', explode( ',', wp_unslash( $_GET['rating_filter'] ) ) ) ) : array(); // WPCS: input var ok, CSRF ok, sanitization ok. $base_link = remove_query_arg( 'paged', $this->get_current_page_url() ); $this->widget_start( $args, $instance ); echo '
    '; for ( $rating = 5; $rating >= 1; $rating-- ) { $count = $this->get_filtered_product_count( $rating ); if ( empty( $count ) ) { continue; } $found = true; $link = $base_link; if ( in_array( $rating, $rating_filter, true ) ) { $link_ratings = implode( ',', array_diff( $rating_filter, array( $rating ) ) ); } else { $link_ratings = implode( ',', array_merge( $rating_filter, array( $rating ) ) ); } $class = in_array( $rating, $rating_filter, true ) ? 'kkart-layered-nav-rating chosen' : 'kkart-layered-nav-rating'; $link = apply_filters( 'kkart_rating_filter_link', $link_ratings ? add_query_arg( 'rating_filter', $link_ratings, $link ) : remove_query_arg( 'rating_filter' ) ); $rating_html = kkart_get_star_rating_html( $rating ); $count_html = wp_kses( apply_filters( 'kkart_rating_filter_count', "({$count})", $count, $rating ), array( 'em' => array(), 'span' => array(), 'strong' => array(), ) ); printf( '
  • %s %s
  • ', esc_attr( $class ), esc_url( $link ), $rating_html, $count_html ); // WPCS: XSS ok. } echo '
'; $this->widget_end( $args ); if ( ! $found ) { ob_end_clean(); } else { echo ob_get_clean(); // WPCS: XSS ok. } } } PK!پ!!1widgets/class-kkart-widget-product-categories.phpnu[widget_cssclass = 'kkart widget_product_categories'; $this->widget_description = __( 'A list or dropdown of product categories.', 'kkart' ); $this->widget_id = 'kkart_product_categories'; $this->widget_name = __( 'Product Categories', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Product categories', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), 'orderby' => array( 'type' => 'select', 'std' => 'name', 'label' => __( 'Order by', 'kkart' ), 'options' => array( 'order' => __( 'Category order', 'kkart' ), 'name' => __( 'Name', 'kkart' ), ), ), 'dropdown' => array( 'type' => 'checkbox', 'std' => 0, 'label' => __( 'Show as dropdown', 'kkart' ), ), 'count' => array( 'type' => 'checkbox', 'std' => 0, 'label' => __( 'Show product counts', 'kkart' ), ), 'hierarchical' => array( 'type' => 'checkbox', 'std' => 1, 'label' => __( 'Show hierarchy', 'kkart' ), ), 'show_children_only' => array( 'type' => 'checkbox', 'std' => 0, 'label' => __( 'Only show children of the current category', 'kkart' ), ), 'hide_empty' => array( 'type' => 'checkbox', 'std' => 0, 'label' => __( 'Hide empty categories', 'kkart' ), ), 'max_depth' => array( 'type' => 'text', 'std' => '', 'label' => __( 'Maximum depth', 'kkart' ), ), ); parent::__construct(); } /** * Output widget. * * @see WP_Widget * @param array $args Widget arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { global $wp_query, $post; $count = isset( $instance['count'] ) ? $instance['count'] : $this->settings['count']['std']; $hierarchical = isset( $instance['hierarchical'] ) ? $instance['hierarchical'] : $this->settings['hierarchical']['std']; $show_children_only = isset( $instance['show_children_only'] ) ? $instance['show_children_only'] : $this->settings['show_children_only']['std']; $dropdown = isset( $instance['dropdown'] ) ? $instance['dropdown'] : $this->settings['dropdown']['std']; $orderby = isset( $instance['orderby'] ) ? $instance['orderby'] : $this->settings['orderby']['std']; $hide_empty = isset( $instance['hide_empty'] ) ? $instance['hide_empty'] : $this->settings['hide_empty']['std']; $dropdown_args = array( 'hide_empty' => $hide_empty, ); $list_args = array( 'show_count' => $count, 'hierarchical' => $hierarchical, 'taxonomy' => 'product_cat', 'hide_empty' => $hide_empty, ); $max_depth = absint( isset( $instance['max_depth'] ) ? $instance['max_depth'] : $this->settings['max_depth']['std'] ); $list_args['menu_order'] = false; $dropdown_args['depth'] = $max_depth; $list_args['depth'] = $max_depth; if ( 'order' === $orderby ) { $list_args['orderby'] = 'meta_value_num'; $dropdown_args['orderby'] = 'meta_value_num'; $list_args['meta_key'] = 'order'; $dropdown_args['meta_key'] = 'order'; } $this->current_cat = false; $this->cat_ancestors = array(); if ( is_tax( 'product_cat' ) ) { $this->current_cat = $wp_query->queried_object; $this->cat_ancestors = get_ancestors( $this->current_cat->term_id, 'product_cat' ); } elseif ( is_singular( 'product' ) ) { $terms = kkart_get_product_terms( $post->ID, 'product_cat', apply_filters( 'kkart_product_categories_widget_product_terms_args', array( 'orderby' => 'parent', 'order' => 'DESC', ) ) ); if ( $terms ) { $main_term = apply_filters( 'kkart_product_categories_widget_main_term', $terms[0], $terms ); $this->current_cat = $main_term; $this->cat_ancestors = get_ancestors( $main_term->term_id, 'product_cat' ); } } // Show Siblings and Children Only. if ( $show_children_only && $this->current_cat ) { if ( $hierarchical ) { $include = array_merge( $this->cat_ancestors, array( $this->current_cat->term_id ), get_terms( 'product_cat', array( 'fields' => 'ids', 'parent' => 0, 'hierarchical' => true, 'hide_empty' => false, ) ), get_terms( 'product_cat', array( 'fields' => 'ids', 'parent' => $this->current_cat->term_id, 'hierarchical' => true, 'hide_empty' => false, ) ) ); // Gather siblings of ancestors. if ( $this->cat_ancestors ) { foreach ( $this->cat_ancestors as $ancestor ) { $include = array_merge( $include, get_terms( 'product_cat', array( 'fields' => 'ids', 'parent' => $ancestor, 'hierarchical' => false, 'hide_empty' => false, ) ) ); } } } else { // Direct children. $include = get_terms( 'product_cat', array( 'fields' => 'ids', 'parent' => $this->current_cat->term_id, 'hierarchical' => true, 'hide_empty' => false, ) ); } $list_args['include'] = implode( ',', $include ); $dropdown_args['include'] = $list_args['include']; if ( empty( $include ) ) { return; } } elseif ( $show_children_only ) { $dropdown_args['depth'] = 1; $dropdown_args['child_of'] = 0; $dropdown_args['hierarchical'] = 1; $list_args['depth'] = 1; $list_args['child_of'] = 0; $list_args['hierarchical'] = 1; } $this->widget_start( $args, $instance ); if ( $dropdown ) { kkart_product_dropdown_categories( apply_filters( 'kkart_product_categories_widget_dropdown_args', wp_parse_args( $dropdown_args, array( 'show_count' => $count, 'hierarchical' => $hierarchical, 'show_uncategorized' => 0, 'selected' => $this->current_cat ? $this->current_cat->slug : '', ) ) ) ); wp_enqueue_script( 'selectWoo' ); wp_enqueue_style( 'select2' ); kkart_enqueue_js( " jQuery( '.dropdown_product_cat' ).change( function() { if ( jQuery(this).val() != '' ) { var this_page = ''; var home_url = '" . esc_js( home_url( '/' ) ) . "'; if ( home_url.indexOf( '?' ) > 0 ) { this_page = home_url + '&product_cat=' + jQuery(this).val(); } else { this_page = home_url + '?product_cat=' + jQuery(this).val(); } location.href = this_page; } else { location.href = '" . esc_js( kkart_get_page_permalink( 'shop' ) ) . "'; } }); if ( jQuery().selectWoo ) { var kkart_product_cat_select = function() { jQuery( '.dropdown_product_cat' ).selectWoo( { placeholder: '" . esc_js( __( 'Select a category', 'kkart' ) ) . "', minimumResultsForSearch: 5, width: '100%', allowClear: true, language: { noResults: function() { return '" . esc_js( _x( 'No matches found', 'enhanced select', 'kkart' ) ) . "'; } } } ); }; kkart_product_cat_select(); } " ); } else { include_once KKART()->plugin_path() . '/includes/walkers/class-kkart-product-cat-list-walker.php'; $list_args['walker'] = new KKART_Product_Cat_List_Walker(); $list_args['title_li'] = ''; $list_args['pad_counts'] = 1; $list_args['show_option_none'] = __( 'No product categories exist.', 'kkart' ); $list_args['current_category'] = ( $this->current_cat ) ? $this->current_cat->term_id : ''; $list_args['current_category_ancestors'] = $this->cat_ancestors; $list_args['max_depth'] = $max_depth; echo '
    '; wp_list_categories( apply_filters( 'kkart_product_categories_widget_args', $list_args ) ); echo '
'; } $this->widget_end( $args ); } } PK!g2widgets/class-kkart-widget-layered-nav-filters.phpnu[widget_cssclass = 'kkart widget_layered_nav_filters'; $this->widget_description = __( 'Display a list of active product filters.', 'kkart' ); $this->widget_id = 'kkart_layered_nav_filters'; $this->widget_name = __( 'Active Product Filters', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Active filters', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), ); parent::__construct(); } /** * Output widget. * * @see WP_Widget * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { if ( ! is_shop() && ! is_product_taxonomy() ) { return; } $_chosen_attributes = KKART_Query::get_layered_nav_chosen_attributes(); $min_price = isset( $_GET['min_price'] ) ? kkart_clean( wp_unslash( $_GET['min_price'] ) ) : 0; // WPCS: input var ok, CSRF ok. $max_price = isset( $_GET['max_price'] ) ? kkart_clean( wp_unslash( $_GET['max_price'] ) ) : 0; // WPCS: input var ok, CSRF ok. $rating_filter = isset( $_GET['rating_filter'] ) ? array_filter( array_map( 'absint', explode( ',', wp_unslash( $_GET['rating_filter'] ) ) ) ) : array(); // WPCS: sanitization ok, input var ok, CSRF ok. $base_link = $this->get_current_page_url(); if ( 0 < count( $_chosen_attributes ) || 0 < $min_price || 0 < $max_price || ! empty( $rating_filter ) ) { $this->widget_start( $args, $instance ); echo '
    '; // Attributes. if ( ! empty( $_chosen_attributes ) ) { foreach ( $_chosen_attributes as $taxonomy => $data ) { foreach ( $data['terms'] as $term_slug ) { $term = get_term_by( 'slug', $term_slug, $taxonomy ); if ( ! $term ) { continue; } $filter_name = 'filter_' . kkart_attribute_taxonomy_slug( $taxonomy ); $current_filter = isset( $_GET[ $filter_name ] ) ? explode( ',', kkart_clean( wp_unslash( $_GET[ $filter_name ] ) ) ) : array(); // WPCS: input var ok, CSRF ok. $current_filter = array_map( 'sanitize_title', $current_filter ); $new_filter = array_diff( $current_filter, array( $term_slug ) ); $link = remove_query_arg( array( 'add-to-cart', $filter_name ), $base_link ); if ( count( $new_filter ) > 0 ) { $link = add_query_arg( $filter_name, implode( ',', $new_filter ), $link ); } $filter_classes = array( 'chosen', 'chosen-' . sanitize_html_class( str_replace( 'pa_', '', $taxonomy ) ), 'chosen-' . sanitize_html_class( str_replace( 'pa_', '', $taxonomy ) . '-' . $term_slug ) ); echo '
  • ' . esc_html( $term->name ) . '
  • '; } } } if ( $min_price ) { $link = remove_query_arg( 'min_price', $base_link ); /* translators: %s: minimum price */ echo '
  • ' . sprintf( __( 'Min %s', 'kkart' ), kkart_price( $min_price ) ) . '
  • '; // WPCS: XSS ok. } if ( $max_price ) { $link = remove_query_arg( 'max_price', $base_link ); /* translators: %s: maximum price */ echo '
  • ' . sprintf( __( 'Max %s', 'kkart' ), kkart_price( $max_price ) ) . '
  • '; // WPCS: XSS ok. } if ( ! empty( $rating_filter ) ) { foreach ( $rating_filter as $rating ) { $link_ratings = implode( ',', array_diff( $rating_filter, array( $rating ) ) ); $link = $link_ratings ? add_query_arg( 'rating_filter', $link_ratings ) : remove_query_arg( 'rating_filter', $base_link ); /* translators: %s: rating */ echo '
  • ' . sprintf( esc_html__( 'Rated %s out of 5', 'kkart' ), esc_html( $rating ) ) . '
  • '; } } echo '
'; $this->widget_end( $args ); } } } PK!12TT+widgets/class-kkart-widget-price-filter.phpnu[widget_cssclass = 'kkart widget_price_filter'; $this->widget_description = __( 'Display a slider to filter products in your store by price.', 'kkart' ); $this->widget_id = 'kkart_price_filter'; $this->widget_name = __( 'Filter Products by Price', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Filter by price', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), ); $suffix = Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min'; $version = Constants::get_constant( 'KKART_VERSION' ); wp_register_script( 'accounting', KKART()->plugin_url() . '/assets/js/accounting/accounting' . $suffix . '.js', array( 'jquery' ), '0.4.2', true ); wp_register_script( 'kkart-jquery-ui-touchpunch', KKART()->plugin_url() . '/assets/js/jquery-ui-touch-punch/jquery-ui-touch-punch' . $suffix . '.js', array( 'jquery-ui-slider' ), $version, true ); wp_register_script( 'kkart-price-slider', KKART()->plugin_url() . '/assets/js/frontend/price-slider' . $suffix . '.js', array( 'jquery-ui-slider', 'kkart-jquery-ui-touchpunch', 'accounting' ), $version, true ); wp_localize_script( 'kkart-price-slider', 'kkart_price_slider_params', array( 'currency_format_num_decimals' => 0, 'currency_format_symbol' => get_kkart_currency_symbol(), 'currency_format_decimal_sep' => esc_attr( kkart_get_price_decimal_separator() ), 'currency_format_thousand_sep' => esc_attr( kkart_get_price_thousand_separator() ), 'currency_format' => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), get_kkart_price_format() ) ), ) ); if ( is_customize_preview() ) { wp_enqueue_script( 'kkart-price-slider' ); } parent::__construct(); } /** * Output widget. * * @see WP_Widget * * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { global $wp; // Requires lookup table added in 3.6. if ( version_compare( get_option( 'kkart_db_version', null ), '3.6', '<' ) ) { return; } if ( ! is_shop() && ! is_product_taxonomy() ) { return; } // If there are not posts and we're not filtering, hide the widget. if ( ! KKART()->query->get_main_query()->post_count && ! isset( $_GET['min_price'] ) && ! isset( $_GET['max_price'] ) ) { // WPCS: input var ok, CSRF ok. return; } wp_enqueue_script( 'kkart-price-slider' ); // Round values to nearest 10 by default. $step = max( apply_filters( 'kkart_price_filter_widget_step', 10 ), 1 ); // Find min and max price in current result set. $prices = $this->get_filtered_price(); $min_price = $prices->min_price; $max_price = $prices->max_price; // Check to see if we should add taxes to the prices if store are excl tax but display incl. $tax_display_mode = get_option( 'kkart_tax_display_shop' ); if ( kkart_tax_enabled() && ! kkart_prices_include_tax() && 'incl' === $tax_display_mode ) { $tax_class = apply_filters( 'kkart_price_filter_widget_tax_class', '' ); // Uses standard tax class. $tax_rates = KKART_Tax::get_rates( $tax_class ); if ( $tax_rates ) { $min_price += KKART_Tax::get_tax_total( KKART_Tax::calc_exclusive_tax( $min_price, $tax_rates ) ); $max_price += KKART_Tax::get_tax_total( KKART_Tax::calc_exclusive_tax( $max_price, $tax_rates ) ); } } $min_price = apply_filters( 'kkart_price_filter_widget_min_amount', floor( $min_price / $step ) * $step ); $max_price = apply_filters( 'kkart_price_filter_widget_max_amount', ceil( $max_price / $step ) * $step ); // If both min and max are equal, we don't need a slider. if ( $min_price === $max_price ) { return; } $current_min_price = isset( $_GET['min_price'] ) ? floor( floatval( wp_unslash( $_GET['min_price'] ) ) / $step ) * $step : $min_price; // WPCS: input var ok, CSRF ok. $current_max_price = isset( $_GET['max_price'] ) ? ceil( floatval( wp_unslash( $_GET['max_price'] ) ) / $step ) * $step : $max_price; // WPCS: input var ok, CSRF ok. $this->widget_start( $args, $instance ); if ( '' === get_option( 'permalink_structure' ) ) { $form_action = remove_query_arg( array( 'page', 'paged', 'product-page' ), add_query_arg( $wp->query_string, '', home_url( $wp->request ) ) ); } else { $form_action = preg_replace( '%\/page/[0-9]+%', '', home_url( trailingslashit( $wp->request ) ) ); } kkart_get_template( 'content-widget-price-filter.php', array( 'form_action' => $form_action, 'step' => $step, 'min_price' => $min_price, 'max_price' => $max_price, 'current_min_price' => $current_min_price, 'current_max_price' => $current_max_price, ) ); $this->widget_end( $args ); } /** * Get filtered min price for current products. * * @return int */ protected function get_filtered_price() { global $wpdb; $args = KKART()->query->get_main_query()->query_vars; $tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array(); $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array(); if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) { $tax_query[] = KKART()->query->get_main_tax_query(); } foreach ( $meta_query + $tax_query as $key => $query ) { if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) { unset( $meta_query[ $key ] ); } } $meta_query = new WP_Meta_Query( $meta_query ); $tax_query = new WP_Tax_Query( $tax_query ); $search = KKART_Query::get_main_search_query_sql(); $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' ); $tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' ); $search_query_sql = $search ? ' AND ' . $search : ''; $sql = " SELECT min( min_price ) as min_price, MAX( max_price ) as max_price FROM {$wpdb->kkart_product_meta_lookup} WHERE product_id IN ( SELECT ID FROM {$wpdb->posts} " . $tax_query_sql['join'] . $meta_query_sql['join'] . " WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'kkart_price_filter_post_type', array( 'product' ) ) ) ) . "') AND {$wpdb->posts}.post_status = 'publish' " . $tax_query_sql['where'] . $meta_query_sql['where'] . $search_query_sql . ' )'; $sql = apply_filters( 'kkart_price_filter_sql', $sql, $meta_query_sql, $tax_query_sql ); return $wpdb->get_row( $sql ); // WPCS: unprepared SQL ok. } } PK!qn` ` 0widgets/class-kkart-widget-product-tag-cloud.phpnu[widget_cssclass = 'kkart widget_product_tag_cloud'; $this->widget_description = __( 'A cloud of your most used product tags.', 'kkart' ); $this->widget_id = 'kkart_product_tag_cloud'; $this->widget_name = __( 'Product Tag Cloud', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Product tags', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), ); parent::__construct(); } /** * Output widget. * * @see WP_Widget * * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { $current_taxonomy = $this->get_current_taxonomy( $instance ); if ( empty( $instance['title'] ) ) { $taxonomy = get_taxonomy( $current_taxonomy ); $instance['title'] = $taxonomy->labels->name; } $this->widget_start( $args, $instance ); echo '
'; wp_tag_cloud( apply_filters( 'kkart_product_tag_cloud_widget_args', array( 'taxonomy' => $current_taxonomy, 'topic_count_text_callback' => array( $this, 'topic_count_text' ), ) ) ); echo '
'; $this->widget_end( $args ); } /** * Return the taxonomy being displayed. * * @param object $instance Widget instance. * @return string */ public function get_current_taxonomy( $instance ) { return 'product_tag'; } /** * Returns topic count text. * * @since 3.4.0 * @param int $count Count text. * @return string */ public function topic_count_text( $count ) { /* translators: %s: product count */ return sprintf( _n( '%s product', '%s products', $count, 'kkart' ), number_format_i18n( $count ) ); } // Ignore whole block to avoid warnings about PSR2.Methods.MethodDeclaration.Underscore violation. // @codingStandardsIgnoreStart /** * Return the taxonomy being displayed. * * @deprecated 3.4.0 * @param object $instance Widget instance. * @return string */ public function _get_current_taxonomy( $instance ) { kkart_deprecated_function( '_get_current_taxonomy', '3.4.0', 'KKART_Widget_Product_Tag_Cloud->get_current_taxonomy' ); return $this->get_current_taxonomy( $instance ); } /** * Returns topic count text. * * @deprecated 3.4.0 * @since 2.6.0 * @param int $count Count text. * @return string */ public function _topic_count_text( $count ) { kkart_deprecated_function( '_topic_count_text', '3.4.0', 'KKART_Widget_Product_Tag_Cloud->topic_count_text' ); return $this->topic_count_text( $count ); } // @codingStandardsIgnoreEnd } PK!,;y\ \ 1widgets/class-kkart-widget-top-rated-products.phpnu[widget_cssclass = 'kkart widget_top_rated_products'; $this->widget_description = __( "A list of your store's top-rated products.", 'kkart' ); $this->widget_id = 'kkart_top_rated_products'; $this->widget_name = __( 'Products by Rating', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Top rated products', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), 'number' => array( 'type' => 'number', 'step' => 1, 'min' => 1, 'max' => '', 'std' => 5, 'label' => __( 'Number of products to show', 'kkart' ), ), ); parent::__construct(); } /** * Output widget. * * @see WP_Widget * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { if ( $this->get_cached_widget( $args ) ) { return; } ob_start(); $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : $this->settings['number']['std']; $query_args = apply_filters( 'kkart_top_rated_products_widget_args', array( 'posts_per_page' => $number, 'no_found_rows' => 1, 'post_status' => 'publish', 'post_type' => 'product', 'meta_key' => '_kkart_average_rating', 'orderby' => 'meta_value_num', 'order' => 'DESC', 'meta_query' => KKART()->query->get_meta_query(), 'tax_query' => KKART()->query->get_tax_query(), ) ); // WPCS: slow query ok. $r = new WP_Query( $query_args ); if ( $r->have_posts() ) { $this->widget_start( $args, $instance ); echo wp_kses_post( apply_filters( 'kkart_before_widget_product_list', '
    ' ) ); $template_args = array( 'widget_id' => isset( $args['widget_id'] ) ? $args['widget_id'] : $this->widget_id, 'show_rating' => true, ); while ( $r->have_posts() ) { $r->the_post(); kkart_get_template( 'content-widget-product.php', $template_args ); } echo wp_kses_post( apply_filters( 'kkart_after_widget_product_list', '
' ) ); $this->widget_end( $args ); } wp_reset_postdata(); $content = ob_get_clean(); echo $content; // WPCS: XSS ok. $this->cache_widget( $args, $content ); } } PK!5b-widgets/class-kkart-widget-product-search.phpnu[widget_cssclass = 'kkart widget_product_search'; $this->widget_description = __( 'A search form for your store.', 'kkart' ); $this->widget_id = 'kkart_product_search'; $this->widget_name = __( 'Product Search', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => '', 'label' => __( 'Title', 'kkart' ), ), ); parent::__construct(); } /** * Output widget. * * @see WP_Widget * * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { $this->widget_start( $args, $instance ); get_product_search_form(); $this->widget_end( $args ); } } PK!w*#widgets/class-kkart-widget-cart.phpnu[widget_cssclass = 'kkart widget_shopping_cart'; $this->widget_description = __( 'Display the customer shopping cart.', 'kkart' ); $this->widget_id = 'kkart_widget_cart'; $this->widget_name = __( 'Cart', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Cart', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), 'hide_if_empty' => array( 'type' => 'checkbox', 'std' => 0, 'label' => __( 'Hide if cart is empty', 'kkart' ), ), ); if ( is_customize_preview() ) { wp_enqueue_script( 'kkart-cart-fragments' ); } parent::__construct(); } /** * Output widget. * * @see WP_Widget * * @param array $args Arguments. * @param array $instance Widget instance. */ public function widget( $args, $instance ) { if ( apply_filters( 'kkart_widget_cart_is_hidden', is_cart() || is_checkout() ) ) { return; } $hide_if_empty = empty( $instance['hide_if_empty'] ) ? 0 : 1; if ( ! isset( $instance['title'] ) ) { $instance['title'] = __( 'Cart', 'kkart' ); } $this->widget_start( $args, $instance ); if ( $hide_if_empty ) { echo '
'; } // Insert cart widget placeholder - code in kkart.js will update this on page load. echo '
'; if ( $hide_if_empty ) { echo '
'; } $this->widget_end( $args ); } } PK!P'widgets/class-kkart-widget-products.phpnu[widget_cssclass = 'kkart widget_products'; $this->widget_description = __( "A list of your store's products.", 'kkart' ); $this->widget_id = 'kkart_products'; $this->widget_name = __( 'Products', 'kkart' ); $this->settings = array( 'title' => array( 'type' => 'text', 'std' => __( 'Products', 'kkart' ), 'label' => __( 'Title', 'kkart' ), ), 'number' => array( 'type' => 'number', 'step' => 1, 'min' => 1, 'max' => '', 'std' => 5, 'label' => __( 'Number of products to show', 'kkart' ), ), 'show' => array( 'type' => 'select', 'std' => '', 'label' => __( 'Show', 'kkart' ), 'options' => array( '' => __( 'All products', 'kkart' ), 'featured' => __( 'Featured products', 'kkart' ), 'onsale' => __( 'On-sale products', 'kkart' ), ), ), 'orderby' => array( 'type' => 'select', 'std' => 'date', 'label' => __( 'Order by', 'kkart' ), 'options' => array( 'date' => __( 'Date', 'kkart' ), 'price' => __( 'Price', 'kkart' ), 'rand' => __( 'Random', 'kkart' ), 'sales' => __( 'Sales', 'kkart' ), ), ), 'order' => array( 'type' => 'select', 'std' => 'desc', 'label' => _x( 'Order', 'Sorting order', 'kkart' ), 'options' => array( 'asc' => __( 'ASC', 'kkart' ), 'desc' => __( 'DESC', 'kkart' ), ), ), 'hide_free' => array( 'type' => 'checkbox', 'std' => 0, 'label' => __( 'Hide free products', 'kkart' ), ), 'show_hidden' => array( 'type' => 'checkbox', 'std' => 0, 'label' => __( 'Show hidden products', 'kkart' ), ), ); parent::__construct(); } /** * Query the products and return them. * * @param array $args Arguments. * @param array $instance Widget instance. * * @return WP_Query */ public function get_products( $args, $instance ) { $number = ! empty( $instance['number'] ) ? absint( $instance['number'] ) : $this->settings['number']['std']; $show = ! empty( $instance['show'] ) ? sanitize_title( $instance['show'] ) : $this->settings['show']['std']; $orderby = ! empty( $instance['orderby'] ) ? sanitize_title( $instance['orderby'] ) : $this->settings['orderby']['std']; $order = ! empty( $instance['order'] ) ? sanitize_title( $instance['order'] ) : $this->settings['order']['std']; $product_visibility_term_ids = kkart_get_product_visibility_term_ids(); $query_args = array( 'posts_per_page' => $number, 'post_status' => 'publish', 'post_type' => 'product', 'no_found_rows' => 1, 'order' => $order, 'meta_query' => array(), 'tax_query' => array( 'relation' => 'AND', ), ); // WPCS: slow query ok. if ( empty( $instance['show_hidden'] ) ) { $query_args['tax_query'][] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => is_search() ? $product_visibility_term_ids['exclude-from-search'] : $product_visibility_term_ids['exclude-from-catalog'], 'operator' => 'NOT IN', ); $query_args['post_parent'] = 0; } if ( ! empty( $instance['hide_free'] ) ) { $query_args['meta_query'][] = array( 'key' => '_price', 'value' => 0, 'compare' => '>', 'type' => 'DECIMAL', ); } if ( 'yes' === get_option( 'kkart_hide_out_of_stock_items' ) ) { $query_args['tax_query'][] = array( array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['outofstock'], 'operator' => 'NOT IN', ), ); // WPCS: slow query ok. } switch ( $show ) { case 'featured': $query_args['tax_query'][] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_term_ids['featured'], ); break; case 'onsale': $product_ids_on_sale = kkart_get_product_ids_on_sale(); $product_ids_on_sale[] = 0; $query_args['post__in'] = $product_ids_on_sale; break; } switch ( $orderby ) { case 'price': $query_args['meta_key'] = '_price'; // WPCS: slow query ok. $query_args['orderby'] = 'meta_value_num'; break; case 'rand': $query_args['orderby'] = 'rand'; break; case 'sales': $query_args['meta_key'] = 'total_sales'; // WPCS: slow query ok. $query_args['orderby'] = 'meta_value_num'; break; default: $query_args['orderby'] = 'date'; } return new WP_Query( apply_filters( 'kkart_products_widget_query_args', $query_args ) ); } /** * Output widget. * * @param array $args Arguments. * @param array $instance Widget instance. * * @see WP_Widget */ public function widget( $args, $instance ) { if ( $this->get_cached_widget( $args ) ) { return; } ob_start(); $products = $this->get_products( $args, $instance ); if ( $products && $products->have_posts() ) { $this->widget_start( $args, $instance ); echo wp_kses_post( apply_filters( 'kkart_before_widget_product_list', '
    ' ) ); $template_args = array( 'widget_id' => isset( $args['widget_id'] ) ? $args['widget_id'] : $this->widget_id, 'show_rating' => true, ); while ( $products->have_posts() ) { $products->the_post(); kkart_get_template( 'content-widget-product.php', $template_args ); } echo wp_kses_post( apply_filters( 'kkart_after_widget_product_list', '
' ) ); $this->widget_end( $args ); } wp_reset_postdata(); echo $this->cache_widget( $args, ob_get_clean() ); // WPCS: XSS ok. } } PK! XXclass-kkart-emails.phpnu[push_to_queue( array( 'filter' => current_filter(), 'args' => func_get_args(), ) ); } else { self::send_transactional_email( ...$args ); } } /** * Init the mailer instance and call the notifications for the current filter. * * @internal * * @param string $filter Filter name. * @param array $args Email args (default: []). */ public static function send_queued_transactional_email( $filter = '', $args = array() ) { if ( apply_filters( 'kkart_allow_send_queued_transactional_email', true, $filter, $args ) ) { self::instance(); // Init self so emails exist. // Ensure gateways are loaded in case they need to insert data into the emails. KKART()->payment_gateways(); KKART()->shipping(); do_action_ref_array( $filter . '_notification', $args ); } } /** * Init the mailer instance and call the notifications for the current filter. * * @internal * * @param array $args Email args (default: []). */ public static function send_transactional_email( $args = array() ) { try { $args = func_get_args(); self::instance(); // Init self so emails exist. do_action_ref_array( current_filter() . '_notification', $args ); } catch ( Exception $e ) { $error = 'Transactional email triggered fatal error for callback ' . current_filter(); $logger = kkart_get_logger(); $logger->critical( $error . PHP_EOL, array( 'source' => 'transactional-emails', ) ); if ( Constants::is_true( 'WP_DEBUG' ) ) { trigger_error( $error, E_USER_WARNING ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped, WordPress.PHP.DevelopmentFunctions.error_log_trigger_error } } } /** * Constructor for the email class hooks in all emails that can be sent. */ public function __construct() { $this->init(); // Email Header, Footer and content hooks. add_action( 'kkart_email_header', array( $this, 'email_header' ) ); add_action( 'kkart_email_footer', array( $this, 'email_footer' ) ); add_action( 'kkart_email_order_details', array( $this, 'order_downloads' ), 10, 4 ); add_action( 'kkart_email_order_details', array( $this, 'order_details' ), 10, 4 ); add_action( 'kkart_email_order_meta', array( $this, 'order_meta' ), 10, 3 ); add_action( 'kkart_email_customer_details', array( $this, 'customer_details' ), 10, 3 ); add_action( 'kkart_email_customer_details', array( $this, 'email_addresses' ), 20, 3 ); // Hooks for sending emails during store events. add_action( 'kkart_low_stock_notification', array( $this, 'low_stock' ) ); add_action( 'kkart_no_stock_notification', array( $this, 'no_stock' ) ); add_action( 'kkart_product_on_backorder_notification', array( $this, 'backorder' ) ); add_action( 'kkart_created_customer_notification', array( $this, 'customer_new_account' ), 10, 3 ); // Hook for replacing {site_title} in email-footer. add_filter( 'kkart_email_footer_text', array( $this, 'replace_placeholders' ) ); // Let 3rd parties unhook the above via this hook. do_action( 'kkart_email', $this ); } /** * Init email classes. */ public function init() { // Include email classes. include_once dirname( __FILE__ ) . '/emails/class-kkart-email.php'; $this->emails['KKART_Email_New_Order'] = include __DIR__ . '/emails/class-kkart-email-new-order.php'; $this->emails['KKART_Email_Cancelled_Order'] = include __DIR__ . '/emails/class-kkart-email-cancelled-order.php'; $this->emails['KKART_Email_Failed_Order'] = include __DIR__ . '/emails/class-kkart-email-failed-order.php'; $this->emails['KKART_Email_Customer_On_Hold_Order'] = include __DIR__ . '/emails/class-kkart-email-customer-on-hold-order.php'; $this->emails['KKART_Email_Customer_Processing_Order'] = include __DIR__ . '/emails/class-kkart-email-customer-processing-order.php'; $this->emails['KKART_Email_Customer_Completed_Order'] = include __DIR__ . '/emails/class-kkart-email-customer-completed-order.php'; $this->emails['KKART_Email_Customer_Refunded_Order'] = include __DIR__ . '/emails/class-kkart-email-customer-refunded-order.php'; $this->emails['KKART_Email_Customer_Invoice'] = include __DIR__ . '/emails/class-kkart-email-customer-invoice.php'; $this->emails['KKART_Email_Customer_Note'] = include __DIR__ . '/emails/class-kkart-email-customer-note.php'; $this->emails['KKART_Email_Customer_Reset_Password'] = include __DIR__ . '/emails/class-kkart-email-customer-reset-password.php'; $this->emails['KKART_Email_Customer_New_Account'] = include __DIR__ . '/emails/class-kkart-email-customer-new-account.php'; $this->emails = apply_filters( 'kkart_email_classes', $this->emails ); } /** * Return the email classes - used in admin to load settings. * * @return KKART_Email[] */ public function get_emails() { return $this->emails; } /** * Get from name for email. * * @return string */ public function get_from_name() { return wp_specialchars_decode( get_option( 'kkart_email_from_name' ), ENT_QUOTES ); } /** * Get from email address. * * @return string */ public function get_from_address() { return sanitize_email( get_option( 'kkart_email_from_address' ) ); } /** * Get the email header. * * @param mixed $email_heading Heading for the email. */ public function email_header( $email_heading ) { kkart_get_template( 'emails/email-header.php', array( 'email_heading' => $email_heading ) ); } /** * Get the email footer. */ public function email_footer() { kkart_get_template( 'emails/email-footer.php' ); } /** * Replace placeholder text in strings. * * @since 3.7.0 * @param string $string Email footer text. * @return string Email footer text with any replacements done. */ public function replace_placeholders( $string ) { $domain = wp_parse_url( home_url(), PHP_URL_HOST ); return str_replace( array( '{site_title}', '{site_address}', '{site_url}', '{kkart}', '{Kkart}', ), array( $this->get_blogname(), $domain, $domain, 'Kkart', 'Kkart', ), $string ); } /** * Filter callback to replace {site_title} in email footer * * @since 3.3.0 * @deprecated 3.7.0 * @param string $string Email footer text. * @return string Email footer text with any replacements done. */ public function email_footer_replace_site_title( $string ) { kkart_deprecated_function( 'KKART_Emails::email_footer_replace_site_title', '3.7.0', 'KKART_Emails::replace_placeholders' ); return $this->replace_placeholders( $string ); } /** * Wraps a message in the kkart mail template. * * @param string $email_heading Heading text. * @param string $message Email message. * @param bool $plain_text Set true to send as plain text. Default to false. * * @return string */ public function wrap_message( $email_heading, $message, $plain_text = false ) { // Buffer. ob_start(); do_action( 'kkart_email_header', $email_heading, null ); echo wpautop( wptexturize( $message ) ); // WPCS: XSS ok. do_action( 'kkart_email_footer', null ); // Get contents. $message = ob_get_clean(); return $message; } /** * Send the email. * * @param mixed $to Receiver. * @param mixed $subject Email subject. * @param mixed $message Message. * @param string $headers Email headers (default: "Content-Type: text/html\r\n"). * @param string $attachments Attachments (default: ""). * @return bool */ public function send( $to, $subject, $message, $headers = "Content-Type: text/html\r\n", $attachments = '' ) { // Send. $email = new KKART_Email(); return $email->send( $to, $subject, $message, $headers, $attachments ); } /** * Prepare and send the customer invoice email on demand. * * @param int|KKART_Order $order Order instance or ID. */ public function customer_invoice( $order ) { $email = $this->emails['KKART_Email_Customer_Invoice']; if ( ! is_object( $order ) ) { $order = kkart_get_order( absint( $order ) ); } $email->trigger( $order->get_id(), $order ); } /** * Customer new account welcome email. * * @param int $customer_id Customer ID. * @param array $new_customer_data New customer data. * @param bool $password_generated If password is generated. */ public function customer_new_account( $customer_id, $new_customer_data = array(), $password_generated = false ) { if ( ! $customer_id ) { return; } $user_pass = ! empty( $new_customer_data['user_pass'] ) ? $new_customer_data['user_pass'] : ''; $email = $this->emails['KKART_Email_Customer_New_Account']; $email->trigger( $customer_id, $user_pass, $password_generated ); } /** * Show the order details table * * @param KKART_Order $order Order instance. * @param bool $sent_to_admin If should sent to admin. * @param bool $plain_text If is plain text email. * @param string $email Email address. */ public function order_details( $order, $sent_to_admin = false, $plain_text = false, $email = '' ) { if ( $plain_text ) { kkart_get_template( 'emails/plain/email-order-details.php', array( 'order' => $order, 'sent_to_admin' => $sent_to_admin, 'plain_text' => $plain_text, 'email' => $email, ) ); } else { kkart_get_template( 'emails/email-order-details.php', array( 'order' => $order, 'sent_to_admin' => $sent_to_admin, 'plain_text' => $plain_text, 'email' => $email, ) ); } } /** * Show order downloads in a table. * * @since 3.2.0 * @param KKART_Order $order Order instance. * @param bool $sent_to_admin If should sent to admin. * @param bool $plain_text If is plain text email. * @param string $email Email address. */ public function order_downloads( $order, $sent_to_admin = false, $plain_text = false, $email = '' ) { $show_downloads = $order->has_downloadable_item() && $order->is_download_permitted() && ! $sent_to_admin && ! is_a( $email, 'KKART_Email_Customer_Refunded_Order' ); if ( ! $show_downloads ) { return; } $downloads = $order->get_downloadable_items(); $columns = apply_filters( 'kkart_email_downloads_columns', array( 'download-product' => __( 'Product', 'kkart' ), 'download-expires' => __( 'Expires', 'kkart' ), 'download-file' => __( 'Download', 'kkart' ), ) ); if ( $plain_text ) { kkart_get_template( 'emails/plain/email-downloads.php', array( 'order' => $order, 'sent_to_admin' => $sent_to_admin, 'plain_text' => $plain_text, 'email' => $email, 'downloads' => $downloads, 'columns' => $columns, ) ); } else { kkart_get_template( 'emails/email-downloads.php', array( 'order' => $order, 'sent_to_admin' => $sent_to_admin, 'plain_text' => $plain_text, 'email' => $email, 'downloads' => $downloads, 'columns' => $columns, ) ); } } /** * Add order meta to email templates. * * @param KKART_Order $order Order instance. * @param bool $sent_to_admin If should sent to admin. * @param bool $plain_text If is plain text email. */ public function order_meta( $order, $sent_to_admin = false, $plain_text = false ) { $fields = apply_filters( 'kkart_email_order_meta_fields', array(), $sent_to_admin, $order ); /** * Deprecated kkart_email_order_meta_keys filter. * * @since 2.3.0 */ $_fields = apply_filters( 'kkart_email_order_meta_keys', array(), $sent_to_admin ); if ( $_fields ) { foreach ( $_fields as $key => $field ) { if ( is_numeric( $key ) ) { $key = $field; } $fields[ $key ] = array( 'label' => wptexturize( $key ), 'value' => wptexturize( get_post_meta( $order->get_id(), $field, true ) ), ); } } if ( $fields ) { if ( $plain_text ) { foreach ( $fields as $field ) { if ( isset( $field['label'] ) && isset( $field['value'] ) && $field['value'] ) { echo $field['label'] . ': ' . $field['value'] . "\n"; // WPCS: XSS ok. } } } else { foreach ( $fields as $field ) { if ( isset( $field['label'] ) && isset( $field['value'] ) && $field['value'] ) { echo '

' . $field['label'] . ': ' . $field['value'] . '

'; // WPCS: XSS ok. } } } } } /** * Is customer detail field valid? * * @param array $field Field data to check if is valid. * @return boolean */ public function customer_detail_field_is_valid( $field ) { return isset( $field['label'] ) && ! empty( $field['value'] ); } /** * Allows developers to add additional customer details to templates. * * In versions prior to 3.2 this was used for notes, phone and email but this data has moved. * * @param KKART_Order $order Order instance. * @param bool $sent_to_admin If should sent to admin. * @param bool $plain_text If is plain text email. */ public function customer_details( $order, $sent_to_admin = false, $plain_text = false ) { if ( ! is_a( $order, 'KKART_Order' ) ) { return; } $fields = array_filter( apply_filters( 'kkart_email_customer_details_fields', array(), $sent_to_admin, $order ), array( $this, 'customer_detail_field_is_valid' ) ); if ( ! empty( $fields ) ) { if ( $plain_text ) { kkart_get_template( 'emails/plain/email-customer-details.php', array( 'fields' => $fields ) ); } else { kkart_get_template( 'emails/email-customer-details.php', array( 'fields' => $fields ) ); } } } /** * Get the email addresses. * * @param KKART_Order $order Order instance. * @param bool $sent_to_admin If should sent to admin. * @param bool $plain_text If is plain text email. */ public function email_addresses( $order, $sent_to_admin = false, $plain_text = false ) { if ( ! is_a( $order, 'KKART_Order' ) ) { return; } if ( $plain_text ) { kkart_get_template( 'emails/plain/email-addresses.php', array( 'order' => $order, 'sent_to_admin' => $sent_to_admin, ) ); } else { kkart_get_template( 'emails/email-addresses.php', array( 'order' => $order, 'sent_to_admin' => $sent_to_admin, ) ); } } /** * Get blog name formatted for emails. * * @return string */ private function get_blogname() { return wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ); } /** * Low stock notification email. * * @param KKART_Product $product Product instance. */ public function low_stock( $product ) { if ( 'no' === get_option( 'kkart_notify_low_stock', 'yes' ) ) { return; } /** * Determine if the current product should trigger a low stock notification * * @param int $product_id - The low stock product id * * @since 4.7.0 */ if ( false === apply_filters( 'kkart_should_send_low_stock_notification', true, $product->get_id() ) ) { return; } $subject = sprintf( '[%s] %s', $this->get_blogname(), __( 'Product low in stock', 'kkart' ) ); $message = sprintf( /* translators: 1: product name 2: items in stock */ __( '%1$s is low in stock. There are %2$d left.', 'kkart' ), html_entity_decode( wp_strip_all_tags( $product->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ), html_entity_decode( wp_strip_all_tags( $product->get_stock_quantity() ) ) ); wp_mail( apply_filters( 'kkart_email_recipient_low_stock', get_option( 'kkart_stock_email_recipient' ), $product, null ), apply_filters( 'kkart_email_subject_low_stock', $subject, $product, null ), apply_filters( 'kkart_email_content_low_stock', $message, $product ), apply_filters( 'kkart_email_headers', '', 'low_stock', $product, null ), apply_filters( 'kkart_email_attachments', array(), 'low_stock', $product, null ) ); } /** * No stock notification email. * * @param KKART_Product $product Product instance. */ public function no_stock( $product ) { if ( 'no' === get_option( 'kkart_notify_no_stock', 'yes' ) ) { return; } /** * Determine if the current product should trigger a no stock notification * * @param int $product_id - The out of stock product id * * @since 4.6.0 */ if ( false === apply_filters( 'kkart_should_send_no_stock_notification', true, $product->get_id() ) ) { return; } $subject = sprintf( '[%s] %s', $this->get_blogname(), __( 'Product out of stock', 'kkart' ) ); /* translators: %s: product name */ $message = sprintf( __( '%s is out of stock.', 'kkart' ), html_entity_decode( wp_strip_all_tags( $product->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ) ); wp_mail( apply_filters( 'kkart_email_recipient_no_stock', get_option( 'kkart_stock_email_recipient' ), $product, null ), apply_filters( 'kkart_email_subject_no_stock', $subject, $product, null ), apply_filters( 'kkart_email_content_no_stock', $message, $product ), apply_filters( 'kkart_email_headers', '', 'no_stock', $product, null ), apply_filters( 'kkart_email_attachments', array(), 'no_stock', $product, null ) ); } /** * Backorder notification email. * * @param array $args Arguments. */ public function backorder( $args ) { $args = wp_parse_args( $args, array( 'product' => '', 'quantity' => '', 'order_id' => '', ) ); $order = kkart_get_order( $args['order_id'] ); if ( ! $args['product'] || ! is_object( $args['product'] ) || ! $args['quantity'] || ! $order ) { return; } $subject = sprintf( '[%s] %s', $this->get_blogname(), __( 'Product backorder', 'kkart' ) ); /* translators: 1: product quantity 2: product name 3: order number */ $message = sprintf( __( '%1$s units of %2$s have been backordered in order #%3$s.', 'kkart' ), $args['quantity'], html_entity_decode( wp_strip_all_tags( $args['product']->get_formatted_name() ), ENT_QUOTES, get_bloginfo( 'charset' ) ), $order->get_order_number() ); wp_mail( apply_filters( 'kkart_email_recipient_backorder', get_option( 'kkart_stock_email_recipient' ), $args, null ), apply_filters( 'kkart_email_subject_backorder', $subject, $args, null ), apply_filters( 'kkart_email_content_backorder', $message, $args ), apply_filters( 'kkart_email_headers', '', 'backorder', $args, null ), apply_filters( 'kkart_email_attachments', array(), 'backorder', $args, null ) ); } /** * Adds Schema.org markup for order in JSON-LD format. * * @deprecated 3.0.0 * @see KKART_Structured_Data::generate_order_data() * * @since 2.6.0 * @param KKART_Order $order Order instance. * @param bool $sent_to_admin If should sent to admin. * @param bool $plain_text If is plain text email. */ public function order_schema_markup( $order, $sent_to_admin = false, $plain_text = false ) { kkart_deprecated_function( 'KKART_Emails::order_schema_markup', '3.0', 'KKART_Structured_Data::generate_order_data' ); KKART()->structured_data->generate_order_data( $order, $sent_to_admin, $plain_text ); KKART()->structured_data->output_structured_data(); } } PK!2l1class-kkart-cart.phpnu[ 0, 'subtotal_tax' => 0, 'shipping_total' => 0, 'shipping_tax' => 0, 'shipping_taxes' => array(), 'discount_total' => 0, 'discount_tax' => 0, 'cart_contents_total' => 0, 'cart_contents_tax' => 0, 'cart_contents_taxes' => array(), 'fee_total' => 0, 'fee_tax' => 0, 'fee_taxes' => array(), 'total' => 0, 'total_tax' => 0, ); /** * Store calculated totals. * * @var array */ protected $totals = array(); /** * Reference to the cart session handling class. * * @var KKART_Cart_Session */ protected $session; /** * Reference to the cart fees API class. * * @var KKART_Cart_Fees */ protected $fees_api; /** * Constructor for the cart class. Loads options and hooks in the init method. */ public function __construct() { $this->session = new KKART_Cart_Session( $this ); $this->fees_api = new KKART_Cart_Fees( $this ); // Register hooks for the objects. $this->session->init(); add_action( 'kkart_add_to_cart', array( $this, 'calculate_totals' ), 20, 0 ); add_action( 'kkart_applied_coupon', array( $this, 'calculate_totals' ), 20, 0 ); add_action( 'kkart_cart_item_removed', array( $this, 'calculate_totals' ), 20, 0 ); add_action( 'kkart_cart_item_restored', array( $this, 'calculate_totals' ), 20, 0 ); add_action( 'kkart_check_cart_items', array( $this, 'check_cart_items' ), 1 ); add_action( 'kkart_check_cart_items', array( $this, 'check_cart_coupons' ), 1 ); add_action( 'kkart_after_checkout_validation', array( $this, 'check_customer_coupons' ), 1, 2 ); } /** * When cloning, ensure object properties are handled. * * These properties store a reference to the cart, so we use new instead of clone. */ public function __clone() { $this->session = clone $this->session; $this->fees_api = clone $this->fees_api; } /* |-------------------------------------------------------------------------- | Getters. |-------------------------------------------------------------------------- | | Methods to retrieve class properties and avoid direct access. */ /** * Gets cart contents. * * @since 3.2.0 * @return array of cart items */ public function get_cart_contents() { return apply_filters( 'kkart_get_cart_contents', (array) $this->cart_contents ); } /** * Return items removed from the cart. * * @since 3.2.0 * @return array */ public function get_removed_cart_contents() { return (array) $this->removed_cart_contents; } /** * Gets the array of applied coupon codes. * * @return array of applied coupons */ public function get_applied_coupons() { return (array) $this->applied_coupons; } /** * Return all calculated coupon totals. * * @since 3.2.0 * @return array */ public function get_coupon_discount_totals() { return (array) $this->coupon_discount_totals; } /** * Return all calculated coupon tax totals. * * @since 3.2.0 * @return array */ public function get_coupon_discount_tax_totals() { return (array) $this->coupon_discount_tax_totals; } /** * Return all calculated totals. * * @since 3.2.0 * @return array */ public function get_totals() { return empty( $this->totals ) ? $this->default_totals : $this->totals; } /** * Get a total. * * @since 3.2.0 * @param string $key Key of element in $totals array. * @return mixed */ protected function get_totals_var( $key ) { return isset( $this->totals[ $key ] ) ? $this->totals[ $key ] : $this->default_totals[ $key ]; } /** * Get subtotal. * * @since 3.2.0 * @return float */ public function get_subtotal() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'subtotal' ) ); } /** * Get subtotal. * * @since 3.2.0 * @return float */ public function get_subtotal_tax() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'subtotal_tax' ) ); } /** * Get discount_total. * * @since 3.2.0 * @return float */ public function get_discount_total() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'discount_total' ) ); } /** * Get discount_tax. * * @since 3.2.0 * @return float */ public function get_discount_tax() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'discount_tax' ) ); } /** * Get shipping_total. * * @since 3.2.0 * @return float */ public function get_shipping_total() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'shipping_total' ) ); } /** * Get shipping_tax. * * @since 3.2.0 * @return float */ public function get_shipping_tax() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'shipping_tax' ) ); } /** * Gets cart total. This is the total of items in the cart, but after discounts. Subtotal is before discounts. * * @since 3.2.0 * @return float */ public function get_cart_contents_total() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'cart_contents_total' ) ); } /** * Gets cart tax amount. * * @since 3.2.0 * @return float */ public function get_cart_contents_tax() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'cart_contents_tax' ) ); } /** * Gets cart total after calculation. * * @since 3.2.0 * @param string $context If the context is view, the value will be formatted for display. This keeps it compatible with pre-3.2 versions. * @return float */ public function get_total( $context = 'view' ) { $total = apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'total' ) ); return 'view' === $context ? apply_filters( 'kkart_cart_total', kkart_price( $total ) ) : $total; } /** * Get total tax amount. * * @since 3.2.0 * @return float */ public function get_total_tax() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'total_tax' ) ); } /** * Get total fee amount. * * @since 3.2.0 * @return float */ public function get_fee_total() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'fee_total' ) ); } /** * Get total fee tax amount. * * @since 3.2.0 * @return float */ public function get_fee_tax() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'fee_tax' ) ); } /** * Get taxes. * * @since 3.2.0 */ public function get_shipping_taxes() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'shipping_taxes' ) ); } /** * Get taxes. * * @since 3.2.0 */ public function get_cart_contents_taxes() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'cart_contents_taxes' ) ); } /** * Get taxes. * * @since 3.2.0 */ public function get_fee_taxes() { return apply_filters( 'kkart_cart_' . __FUNCTION__, $this->get_totals_var( 'fee_taxes' ) ); } /** * Return whether or not the cart is displaying prices including tax, rather than excluding tax. * * @since 3.3.0 * @return bool */ public function display_prices_including_tax() { return apply_filters( 'kkart_cart_' . __FUNCTION__, 'incl' === $this->get_tax_price_display_mode() ); } /* |-------------------------------------------------------------------------- | Setters. |-------------------------------------------------------------------------- | | Methods to set class properties and avoid direct access. */ /** * Sets the contents of the cart. * * @param array $value Cart array. */ public function set_cart_contents( $value ) { $this->cart_contents = (array) $value; } /** * Set items removed from the cart. * * @since 3.2.0 * @param array $value Item array. */ public function set_removed_cart_contents( $value = array() ) { $this->removed_cart_contents = (array) $value; } /** * Sets the array of applied coupon codes. * * @param array $value List of applied coupon codes. */ public function set_applied_coupons( $value = array() ) { $this->applied_coupons = (array) $value; } /** * Sets the array of calculated coupon totals. * * @since 3.2.0 * @param array $value Value to set. */ public function set_coupon_discount_totals( $value = array() ) { $this->coupon_discount_totals = (array) $value; } /** * Sets the array of calculated coupon tax totals. * * @since 3.2.0 * @param array $value Value to set. */ public function set_coupon_discount_tax_totals( $value = array() ) { $this->coupon_discount_tax_totals = (array) $value; } /** * Set all calculated totals. * * @since 3.2.0 * @param array $value Value to set. */ public function set_totals( $value = array() ) { $this->totals = wp_parse_args( $value, $this->default_totals ); } /** * Set subtotal. * * @since 3.2.0 * @param string $value Value to set. */ public function set_subtotal( $value ) { $this->totals['subtotal'] = kkart_format_decimal( $value, kkart_get_price_decimals() ); } /** * Set subtotal. * * @since 3.2.0 * @param string $value Value to set. */ public function set_subtotal_tax( $value ) { $this->totals['subtotal_tax'] = $value; } /** * Set discount_total. * * @since 3.2.0 * @param string $value Value to set. */ public function set_discount_total( $value ) { $this->totals['discount_total'] = $value; } /** * Set discount_tax. * * @since 3.2.0 * @param string $value Value to set. */ public function set_discount_tax( $value ) { $this->totals['discount_tax'] = $value; } /** * Set shipping_total. * * @since 3.2.0 * @param string $value Value to set. */ public function set_shipping_total( $value ) { $this->totals['shipping_total'] = kkart_format_decimal( $value, kkart_get_price_decimals() ); } /** * Set shipping_tax. * * @since 3.2.0 * @param string $value Value to set. */ public function set_shipping_tax( $value ) { $this->totals['shipping_tax'] = $value; } /** * Set cart_contents_total. * * @since 3.2.0 * @param string $value Value to set. */ public function set_cart_contents_total( $value ) { $this->totals['cart_contents_total'] = kkart_format_decimal( $value, kkart_get_price_decimals() ); } /** * Set cart tax amount. * * @since 3.2.0 * @param string $value Value to set. */ public function set_cart_contents_tax( $value ) { $this->totals['cart_contents_tax'] = $value; } /** * Set cart total. * * @since 3.2.0 * @param string $value Value to set. */ public function set_total( $value ) { $this->totals['total'] = kkart_format_decimal( $value, kkart_get_price_decimals() ); } /** * Set total tax amount. * * @since 3.2.0 * @param string $value Value to set. */ public function set_total_tax( $value ) { // We round here because this is a total entry, as opposed to line items in other setters. $this->totals['total_tax'] = kkart_round_tax_total( $value ); } /** * Set fee amount. * * @since 3.2.0 * @param string $value Value to set. */ public function set_fee_total( $value ) { $this->totals['fee_total'] = kkart_format_decimal( $value, kkart_get_price_decimals() ); } /** * Set fee tax. * * @since 3.2.0 * @param string $value Value to set. */ public function set_fee_tax( $value ) { $this->totals['fee_tax'] = $value; } /** * Set taxes. * * @since 3.2.0 * @param array $value Tax values. */ public function set_shipping_taxes( $value ) { $this->totals['shipping_taxes'] = (array) $value; } /** * Set taxes. * * @since 3.2.0 * @param array $value Tax values. */ public function set_cart_contents_taxes( $value ) { $this->totals['cart_contents_taxes'] = (array) $value; } /** * Set taxes. * * @since 3.2.0 * @param array $value Tax values. */ public function set_fee_taxes( $value ) { $this->totals['fee_taxes'] = (array) $value; } /* |-------------------------------------------------------------------------- | Helper methods. |-------------------------------------------------------------------------- */ /** * Returns the cart and shipping taxes, merged. * * @return array merged taxes */ public function get_taxes() { return apply_filters( 'kkart_cart_get_taxes', kkart_array_merge_recursive_numeric( $this->get_shipping_taxes(), $this->get_cart_contents_taxes(), $this->get_fee_taxes() ), $this ); } /** * Returns the contents of the cart in an array. * * @return array contents of the cart */ public function get_cart() { if ( ! did_action( 'wp_loaded' ) ) { kkart_doing_it_wrong( __FUNCTION__, __( 'Get cart should not be called before the wp_loaded action.', 'kkart' ), '2.3' ); } if ( ! did_action( 'kkart_load_cart_from_session' ) ) { $this->session->get_cart_from_session(); } return array_filter( $this->get_cart_contents() ); } /** * Returns a specific item in the cart. * * @param string $item_key Cart item key. * @return array Item data */ public function get_cart_item( $item_key ) { return isset( $this->cart_contents[ $item_key ] ) ? $this->cart_contents[ $item_key ] : array(); } /** * Checks if the cart is empty. * * @return bool */ public function is_empty() { return 0 === count( $this->get_cart() ); } /** * Empties the cart and optionally the persistent cart too. * * @param bool $clear_persistent_cart Should the persistant cart be cleared too. Defaults to true. */ public function empty_cart( $clear_persistent_cart = true ) { do_action( 'kkart_before_cart_emptied', $clear_persistent_cart ); $this->cart_contents = array(); $this->removed_cart_contents = array(); $this->shipping_methods = array(); $this->coupon_discount_totals = array(); $this->coupon_discount_tax_totals = array(); $this->applied_coupons = array(); $this->totals = $this->default_totals; if ( $clear_persistent_cart ) { $this->session->persistent_cart_destroy(); } $this->fees_api->remove_all_fees(); do_action( 'kkart_cart_emptied', $clear_persistent_cart ); } /** * Get number of items in the cart. * * @return int */ public function get_cart_contents_count() { return apply_filters( 'kkart_cart_contents_count', array_sum( wp_list_pluck( $this->get_cart(), 'quantity' ) ) ); } /** * Get weight of items in the cart. * * @since 2.5.0 * @return float */ public function get_cart_contents_weight() { $weight = 0.0; foreach ( $this->get_cart() as $cart_item_key => $values ) { if ( $values['data']->has_weight() ) { $weight += (float) $values['data']->get_weight() * $values['quantity']; } } return apply_filters( 'kkart_cart_contents_weight', $weight ); } /** * Get cart items quantities - merged so we can do accurate stock checks on items across multiple lines. * * @return array */ public function get_cart_item_quantities() { $quantities = array(); foreach ( $this->get_cart() as $cart_item_key => $values ) { $product = $values['data']; $quantities[ $product->get_stock_managed_by_id() ] = isset( $quantities[ $product->get_stock_managed_by_id() ] ) ? $quantities[ $product->get_stock_managed_by_id() ] + $values['quantity'] : $values['quantity']; } return $quantities; } /** * Check all cart items for errors. */ public function check_cart_items() { $return = true; $result = $this->check_cart_item_validity(); if ( is_wp_error( $result ) ) { kkart_add_notice( $result->get_error_message(), 'error' ); $return = false; } $result = $this->check_cart_item_stock(); if ( is_wp_error( $result ) ) { kkart_add_notice( $result->get_error_message(), 'error' ); $return = false; } return $return; } /** * Check cart coupons for errors. */ public function check_cart_coupons() { foreach ( $this->get_applied_coupons() as $code ) { $coupon = new KKART_Coupon( $code ); if ( ! $coupon->is_valid() ) { $coupon->add_coupon_message( KKART_Coupon::E_KKART_COUPON_INVALID_REMOVED ); $this->remove_coupon( $code ); } } } /** * Looks through cart items and checks the posts are not trashed or deleted. * * @return bool|WP_Error */ public function check_cart_item_validity() { $return = true; foreach ( $this->get_cart() as $cart_item_key => $values ) { $product = $values['data']; if ( ! $product || ! $product->exists() || 'trash' === $product->get_status() ) { $this->set_quantity( $cart_item_key, 0 ); $return = new WP_Error( 'invalid', __( 'An item which is no longer available was removed from your cart.', 'kkart' ) ); } } return $return; } /** * Looks through the cart to check each item is in stock. If not, add an error. * * @return bool|WP_Error */ public function check_cart_item_stock() { $error = new WP_Error(); $product_qty_in_cart = $this->get_cart_item_quantities(); $current_session_order_id = isset( KKART()->session->order_awaiting_payment ) ? absint( KKART()->session->order_awaiting_payment ) : 0; foreach ( $this->get_cart() as $cart_item_key => $values ) { $product = $values['data']; // Check stock based on stock-status. if ( ! $product->is_in_stock() ) { /* translators: %s: product name */ $error->add( 'out-of-stock', sprintf( __( 'Sorry, "%s" is not in stock. Please edit your cart and try again. We apologize for any inconvenience caused.', 'kkart' ), $product->get_name() ) ); return $error; } // We only need to check products managing stock, with a limited stock qty. if ( ! $product->managing_stock() || $product->backorders_allowed() ) { continue; } // Check stock based on all items in the cart and consider any held stock within pending orders. $held_stock = kkart_get_held_stock_quantity( $product, $current_session_order_id ); $required_stock = $product_qty_in_cart[ $product->get_stock_managed_by_id() ]; /** * Allows filter if product have enough stock to get added to the cart. * * @since 4.6.0 * @param bool $has_stock If have enough stock. * @param KKART_Product $product Product instance. * @param array $values Cart item values. */ if ( apply_filters( 'kkart_cart_item_required_stock_is_not_enough', $product->get_stock_quantity() < ( $held_stock + $required_stock ), $product, $values ) ) { /* translators: 1: product name 2: quantity in stock */ $error->add( 'out-of-stock', sprintf( __( 'Sorry, we do not have enough "%1$s" in stock to fulfill your order (%2$s available). We apologize for any inconvenience caused.', 'kkart' ), $product->get_name(), kkart_format_stock_quantity_for_display( $product->get_stock_quantity() - $held_stock, $product ) ) ); return $error; } } return true; } /** * Gets and formats a list of cart item data + variations for display on the frontend. * * @param array $cart_item Cart item object. * @param bool $flat Should the data be returned flat or in a list. * @return string */ public function get_item_data( $cart_item, $flat = false ) { kkart_deprecated_function( 'KKART_Cart::get_item_data', '3.3', 'kkart_get_formatted_cart_item_data' ); return kkart_get_formatted_cart_item_data( $cart_item, $flat ); } /** * Gets cross sells based on the items in the cart. * * @return array cross_sells (item ids) */ public function get_cross_sells() { $cross_sells = array(); $in_cart = array(); if ( ! $this->is_empty() ) { foreach ( $this->get_cart() as $cart_item_key => $values ) { if ( $values['quantity'] > 0 ) { $cross_sells = array_merge( $values['data']->get_cross_sell_ids(), $cross_sells ); $in_cart[] = $values['product_id']; } } } $cross_sells = array_diff( $cross_sells, $in_cart ); return apply_filters( 'kkart_cart_crosssell_ids', wp_parse_id_list( $cross_sells ), $this ); } /** * Gets the url to remove an item from the cart. * * @param string $cart_item_key contains the id of the cart item. * @return string url to page */ public function get_remove_url( $cart_item_key ) { kkart_deprecated_function( 'KKART_Cart::get_remove_url', '3.3', 'kkart_get_cart_remove_url' ); return kkart_get_cart_remove_url( $cart_item_key ); } /** * Gets the url to re-add an item into the cart. * * @param string $cart_item_key Cart item key to undo. * @return string url to page */ public function get_undo_url( $cart_item_key ) { kkart_deprecated_function( 'KKART_Cart::get_undo_url', '3.3', 'kkart_get_cart_undo_url' ); return kkart_get_cart_undo_url( $cart_item_key ); } /** * Get taxes, merged by code, formatted ready for output. * * @return array */ public function get_tax_totals() { $shipping_taxes = $this->get_shipping_taxes(); // Shipping taxes are rounded differently, so we will subtract from all taxes, then round and then add them back. $taxes = $this->get_taxes(); $tax_totals = array(); foreach ( $taxes as $key => $tax ) { $code = KKART_Tax::get_rate_code( $key ); if ( $code || apply_filters( 'kkart_cart_remove_taxes_zero_rate_id', 'zero-rated' ) === $key ) { if ( ! isset( $tax_totals[ $code ] ) ) { $tax_totals[ $code ] = new stdClass(); $tax_totals[ $code ]->amount = 0; } $tax_totals[ $code ]->tax_rate_id = $key; $tax_totals[ $code ]->is_compound = KKART_Tax::is_compound( $key ); $tax_totals[ $code ]->label = KKART_Tax::get_rate_label( $key ); if ( isset( $shipping_taxes[ $key ] ) ) { $tax -= $shipping_taxes[ $key ]; $tax = kkart_round_tax_total( $tax ); $tax += NumberUtil::round( $shipping_taxes[ $key ], kkart_get_price_decimals() ); unset( $shipping_taxes[ $key ] ); } $tax_totals[ $code ]->amount += kkart_round_tax_total( $tax ); $tax_totals[ $code ]->formatted_amount = kkart_price( $tax_totals[ $code ]->amount ); } } if ( apply_filters( 'kkart_cart_hide_zero_taxes', true ) ) { $amounts = array_filter( wp_list_pluck( $tax_totals, 'amount' ) ); $tax_totals = array_intersect_key( $tax_totals, $amounts ); } return apply_filters( 'kkart_cart_tax_totals', $tax_totals, $this ); } /** * Get all tax classes for items in the cart. * * @return array */ public function get_cart_item_tax_classes() { $found_tax_classes = array(); foreach ( KKART()->cart->get_cart() as $item ) { if ( $item['data'] && ( $item['data']->is_taxable() || $item['data']->is_shipping_taxable() ) ) { $found_tax_classes[] = $item['data']->get_tax_class(); } } return array_unique( $found_tax_classes ); } /** * Get all tax classes for shipping based on the items in the cart. * * @return array */ public function get_cart_item_tax_classes_for_shipping() { $found_tax_classes = array(); foreach ( KKART()->cart->get_cart() as $item ) { if ( $item['data'] && ( $item['data']->is_shipping_taxable() ) ) { $found_tax_classes[] = $item['data']->get_tax_class(); } } return array_unique( $found_tax_classes ); } /** * Determines the value that the customer spent and the subtotal * displayed, used for things like coupon validation. * * Since the coupon lines are displayed based on the TAX DISPLAY value * of cart, this is used to determine the spend. * * If cart totals are shown including tax, use the subtotal. * If cart totals are shown excluding tax, use the subtotal ex tax * (tax is shown after coupons). * * @since 2.6.0 * @return string */ public function get_displayed_subtotal() { return $this->display_prices_including_tax() ? $this->get_subtotal() + $this->get_subtotal_tax() : $this->get_subtotal(); } /** * Check if product is in the cart and return cart item key. * * Cart item key will be unique based on the item and its properties, such as variations. * * @param mixed $cart_id id of product to find in the cart. * @return string cart item key */ public function find_product_in_cart( $cart_id = false ) { if ( false !== $cart_id ) { if ( is_array( $this->cart_contents ) && isset( $this->cart_contents[ $cart_id ] ) ) { return $cart_id; } } return ''; } /** * Generate a unique ID for the cart item being added. * * @param int $product_id - id of the product the key is being generated for. * @param int $variation_id of the product the key is being generated for. * @param array $variation data for the cart item. * @param array $cart_item_data other cart item data passed which affects this items uniqueness in the cart. * @return string cart item key */ public function generate_cart_id( $product_id, $variation_id = 0, $variation = array(), $cart_item_data = array() ) { $id_parts = array( $product_id ); if ( $variation_id && 0 !== $variation_id ) { $id_parts[] = $variation_id; } if ( is_array( $variation ) && ! empty( $variation ) ) { $variation_key = ''; foreach ( $variation as $key => $value ) { $variation_key .= trim( $key ) . trim( $value ); } $id_parts[] = $variation_key; } if ( is_array( $cart_item_data ) && ! empty( $cart_item_data ) ) { $cart_item_data_key = ''; foreach ( $cart_item_data as $key => $value ) { if ( is_array( $value ) || is_object( $value ) ) { $value = http_build_query( $value ); } $cart_item_data_key .= trim( $key ) . trim( $value ); } $id_parts[] = $cart_item_data_key; } return apply_filters( 'kkart_cart_id', md5( implode( '_', $id_parts ) ), $product_id, $variation_id, $variation, $cart_item_data ); } /** * Add a product to the cart. * * @throws Exception Plugins can throw an exception to prevent adding to cart. * @param int $product_id contains the id of the product to add to the cart. * @param int $quantity contains the quantity of the item to add. * @param int $variation_id ID of the variation being added to the cart. * @param array $variation attribute values. * @param array $cart_item_data extra cart item data we want to pass into the item. * @return string|bool $cart_item_key */ public function add_to_cart( $product_id = 0, $quantity = 1, $variation_id = 0, $variation = array(), $cart_item_data = array() ) { try { $product_id = absint( $product_id ); $variation_id = absint( $variation_id ); // Ensure we don't add a variation to the cart directly by variation ID. if ( 'product_variation' === get_post_type( $product_id ) ) { $variation_id = $product_id; $product_id = wp_get_post_parent_id( $variation_id ); } $product_data = kkart_get_product( $variation_id ? $variation_id : $product_id ); $quantity = apply_filters( 'kkart_add_to_cart_quantity', $quantity, $product_id ); if ( $quantity <= 0 || ! $product_data || 'trash' === $product_data->get_status() ) { return false; } if ( $product_data->is_type( 'variation' ) ) { $missing_attributes = array(); $parent_data = kkart_get_product( $product_data->get_parent_id() ); $variation_attributes = $product_data->get_variation_attributes(); // Filter out 'any' variations, which are empty, as they need to be explicitly specified while adding to cart. $variation_attributes = array_filter( $variation_attributes ); // Gather posted attributes. $posted_attributes = array(); foreach ( $parent_data->get_attributes() as $attribute ) { if ( ! $attribute['is_variation'] ) { continue; } $attribute_key = 'attribute_' . sanitize_title( $attribute['name'] ); if ( isset( $variation[ $attribute_key ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( $attribute['is_taxonomy'] ) { // Don't use kkart_clean as it destroys sanitized characters. $value = sanitize_title( wp_unslash( $variation[ $attribute_key ] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } else { $value = html_entity_decode( kkart_clean( wp_unslash( $variation[ $attribute_key ] ) ), ENT_QUOTES, get_bloginfo( 'charset' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended } // Don't include if it's empty. if ( ! empty( $value ) || '0' === $value ) { $posted_attributes[ $attribute_key ] = $value; } } } // Merge variation attributes and posted attributes. $posted_and_variation_attributes = array_merge( $variation_attributes, $posted_attributes ); // If no variation ID is set, attempt to get a variation ID from posted attributes. if ( empty( $variation_id ) ) { $data_store = KKART_Data_Store::load( 'product' ); $variation_id = $data_store->find_matching_product_variation( $parent_data, $posted_attributes ); } // Do we have a variation ID? if ( empty( $variation_id ) ) { throw new Exception( __( 'Please choose product options…', 'kkart' ) ); } // Check the data we have is valid. $variation_data = kkart_get_product_variation_attributes( $variation_id ); $attributes = array(); foreach ( $parent_data->get_attributes() as $attribute ) { if ( ! $attribute['is_variation'] ) { continue; } // Get valid value from variation data. $attribute_key = 'attribute_' . sanitize_title( $attribute['name'] ); $valid_value = isset( $variation_data[ $attribute_key ] ) ? $variation_data[ $attribute_key ] : ''; /** * If the attribute value was posted, check if it's valid. * * If no attribute was posted, only error if the variation has an 'any' attribute which requires a value. */ if ( isset( $posted_and_variation_attributes[ $attribute_key ] ) ) { $value = $posted_and_variation_attributes[ $attribute_key ]; // Allow if valid or show error. if ( $valid_value === $value ) { $attributes[ $attribute_key ] = $value; } elseif ( '' === $valid_value && in_array( $value, $attribute->get_slugs(), true ) ) { // If valid values are empty, this is an 'any' variation so get all possible values. $attributes[ $attribute_key ] = $value; } else { /* translators: %s: Attribute name. */ throw new Exception( sprintf( __( 'Invalid value posted for %s', 'kkart' ), kkart_attribute_label( $attribute['name'] ) ) ); } } elseif ( '' === $valid_value ) { $missing_attributes[] = kkart_attribute_label( $attribute['name'] ); } $variation = $attributes; } if ( ! empty( $missing_attributes ) ) { /* translators: %s: Attribute name. */ throw new Exception( sprintf( _n( '%s is a required field', '%s are required fields', count( $missing_attributes ), 'kkart' ), kkart_format_list_of_items( $missing_attributes ) ) ); } } // Load cart item data - may be added by other plugins. $cart_item_data = (array) apply_filters( 'kkart_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity ); // Generate a ID based on product ID, variation ID, variation data, and other cart item data. $cart_id = $this->generate_cart_id( $product_id, $variation_id, $variation, $cart_item_data ); // Find the cart item key in the existing cart. $cart_item_key = $this->find_product_in_cart( $cart_id ); // Force quantity to 1 if sold individually and check for existing item in cart. if ( $product_data->is_sold_individually() ) { $quantity = apply_filters( 'kkart_add_to_cart_sold_individually_quantity', 1, $quantity, $product_id, $variation_id, $cart_item_data ); $found_in_cart = apply_filters( 'kkart_add_to_cart_sold_individually_found_in_cart', $cart_item_key && $this->cart_contents[ $cart_item_key ]['quantity'] > 0, $product_id, $variation_id, $cart_item_data, $cart_id ); if ( $found_in_cart ) { /* translators: %s: product name */ $message = sprintf( __( 'You cannot add another "%s" to your cart.', 'kkart' ), $product_data->get_name() ); /** * Filters message about more than 1 product being added to cart. * * @since 4.5.0 * @param string $message Message. * @param KKART_Product $product_data Product data. */ $message = apply_filters( 'kkart_cart_product_cannot_add_another_message', $message, $product_data ); throw new Exception( sprintf( '%s %s', kkart_get_cart_url(), __( 'View cart', 'kkart' ), $message ) ); } } if ( ! $product_data->is_purchasable() ) { $message = __( 'Sorry, this product cannot be purchased.', 'kkart' ); /** * Filters message about product unable to be purchased. * * @since 3.8.0 * @param string $message Message. * @param KKART_Product $product_data Product data. */ $message = apply_filters( 'kkart_cart_product_cannot_be_purchased_message', $message, $product_data ); throw new Exception( $message ); } // Stock check - only check if we're managing stock and backorders are not allowed. if ( ! $product_data->is_in_stock() ) { /* translators: %s: product name */ $message = sprintf( __( 'You cannot add "%s" to the cart because the product is out of stock.', 'kkart' ), $product_data->get_name() ); /** * Filters message about product being out of stock. * * @since 4.5.0 * @param string $message Message. * @param KKART_Product $product_data Product data. */ $message = apply_filters( 'kkart_cart_product_out_of_stock_message', $message, $product_data ); throw new Exception( $message ); } if ( ! $product_data->has_enough_stock( $quantity ) ) { $stock_quantity = $product_data->get_stock_quantity(); /* translators: 1: product name 2: quantity in stock */ $message = sprintf( __( 'You cannot add that amount of "%1$s" to the cart because there is not enough stock (%2$s remaining).', 'kkart' ), $product_data->get_name(), kkart_format_stock_quantity_for_display( $stock_quantity, $product_data ) ); /** * Filters message about product not having enough stock. * * @since 4.5.0 * @param string $message Message. * @param KKART_Product $product_data Product data. * @param int $stock_quantity Quantity remaining. */ $message = apply_filters( 'kkart_cart_product_not_enough_stock_message', $message, $product_data, $stock_quantity ); throw new Exception( $message ); } // Stock check - this time accounting for whats already in-cart. if ( $product_data->managing_stock() ) { $products_qty_in_cart = $this->get_cart_item_quantities(); if ( isset( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] ) && ! $product_data->has_enough_stock( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ] + $quantity ) ) { throw new Exception( sprintf( '%s %s', kkart_get_cart_url(), __( 'View cart', 'kkart' ), /* translators: 1: quantity in stock 2: current quantity */ sprintf( __( 'You cannot add that amount to the cart — we have %1$s in stock and you already have %2$s in your cart.', 'kkart' ), kkart_format_stock_quantity_for_display( $product_data->get_stock_quantity(), $product_data ), kkart_format_stock_quantity_for_display( $products_qty_in_cart[ $product_data->get_stock_managed_by_id() ], $product_data ) ) ) ); } } // If cart_item_key is set, the item is already in the cart. if ( $cart_item_key ) { $new_quantity = $quantity + $this->cart_contents[ $cart_item_key ]['quantity']; $this->set_quantity( $cart_item_key, $new_quantity, false ); } else { $cart_item_key = $cart_id; // Add item after merging with $cart_item_data - hook to allow plugins to modify cart item. $this->cart_contents[ $cart_item_key ] = apply_filters( 'kkart_add_cart_item', array_merge( $cart_item_data, array( 'key' => $cart_item_key, 'product_id' => $product_id, 'variation_id' => $variation_id, 'variation' => $variation, 'quantity' => $quantity, 'data' => $product_data, 'data_hash' => kkart_get_cart_item_data_hash( $product_data ), ) ), $cart_item_key ); } $this->cart_contents = apply_filters( 'kkart_cart_contents_changed', $this->cart_contents ); do_action( 'kkart_add_to_cart', $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ); return $cart_item_key; } catch ( Exception $e ) { if ( $e->getMessage() ) { kkart_add_notice( $e->getMessage(), 'error' ); } return false; } } /** * Remove a cart item. * * @since 2.3.0 * @param string $cart_item_key Cart item key to remove from the cart. * @return bool */ public function remove_cart_item( $cart_item_key ) { if ( isset( $this->cart_contents[ $cart_item_key ] ) ) { $this->removed_cart_contents[ $cart_item_key ] = $this->cart_contents[ $cart_item_key ]; unset( $this->removed_cart_contents[ $cart_item_key ]['data'] ); do_action( 'kkart_remove_cart_item', $cart_item_key, $this ); unset( $this->cart_contents[ $cart_item_key ] ); do_action( 'kkart_cart_item_removed', $cart_item_key, $this ); return true; } return false; } /** * Restore a cart item. * * @param string $cart_item_key Cart item key to restore to the cart. * @return bool */ public function restore_cart_item( $cart_item_key ) { if ( isset( $this->removed_cart_contents[ $cart_item_key ] ) ) { $restore_item = $this->removed_cart_contents[ $cart_item_key ]; $this->cart_contents[ $cart_item_key ] = $restore_item; $this->cart_contents[ $cart_item_key ]['data'] = kkart_get_product( $restore_item['variation_id'] ? $restore_item['variation_id'] : $restore_item['product_id'] ); do_action( 'kkart_restore_cart_item', $cart_item_key, $this ); unset( $this->removed_cart_contents[ $cart_item_key ] ); do_action( 'kkart_cart_item_restored', $cart_item_key, $this ); return true; } return false; } /** * Set the quantity for an item in the cart using it's key. * * @param string $cart_item_key contains the id of the cart item. * @param int $quantity contains the quantity of the item. * @param bool $refresh_totals whether or not to calculate totals after setting the new qty. Can be used to defer calculations if setting quantities in bulk. * @return bool */ public function set_quantity( $cart_item_key, $quantity = 1, $refresh_totals = true ) { if ( 0 === $quantity || $quantity < 0 ) { // If we're setting qty to 0 we're removing the item from the cart. return $this->remove_cart_item( $cart_item_key ); } // Update qty. $old_quantity = $this->cart_contents[ $cart_item_key ]['quantity']; $this->cart_contents[ $cart_item_key ]['quantity'] = $quantity; do_action( 'kkart_after_cart_item_quantity_update', $cart_item_key, $quantity, $old_quantity, $this ); if ( $refresh_totals ) { $this->calculate_totals(); } /** * Fired after qty has been changed. * * @since 3.6.0 * @param string $cart_item_key contains the id of the cart item. This may be empty if the cart item does not exist any more. * @param int $quantity contains the quantity of the item. * @param KKART_Cart $this Cart class. */ do_action( 'kkart_cart_item_set_quantity', $cart_item_key, $quantity, $this ); return true; } /** * Get cart's owner. * * @since 3.2.0 * @return KKART_Customer */ public function get_customer() { return KKART()->customer; } /** * Calculate totals for the items in the cart. * * @uses KKART_Cart_Totals */ public function calculate_totals() { $this->reset_totals(); if ( $this->is_empty() ) { $this->session->set_session(); return; } do_action( 'kkart_before_calculate_totals', $this ); new KKART_Cart_Totals( $this ); do_action( 'kkart_after_calculate_totals', $this ); } /** * Looks at the totals to see if payment is actually required. * * @return bool */ public function needs_payment() { return apply_filters( 'kkart_cart_needs_payment', 0 < $this->get_total( 'edit' ), $this ); } /* * Shipping related functions. */ /** * Uses the shipping class to calculate shipping then gets the totals when its finished. */ public function calculate_shipping() { $this->shipping_methods = $this->needs_shipping() ? $this->get_chosen_shipping_methods( KKART()->shipping()->calculate_shipping( $this->get_shipping_packages() ) ) : array(); $shipping_taxes = wp_list_pluck( $this->shipping_methods, 'taxes' ); $merged_taxes = array(); foreach ( $shipping_taxes as $taxes ) { foreach ( $taxes as $tax_id => $tax_amount ) { if ( ! isset( $merged_taxes[ $tax_id ] ) ) { $merged_taxes[ $tax_id ] = 0; } $merged_taxes[ $tax_id ] += $tax_amount; } } $this->set_shipping_total( array_sum( wp_list_pluck( $this->shipping_methods, 'cost' ) ) ); $this->set_shipping_tax( array_sum( $merged_taxes ) ); $this->set_shipping_taxes( $merged_taxes ); return $this->shipping_methods; } /** * Given a set of packages with rates, get the chosen ones only. * * @since 3.2.0 * @param array $calculated_shipping_packages Array of packages. * @return array */ protected function get_chosen_shipping_methods( $calculated_shipping_packages = array() ) { $chosen_methods = array(); // Get chosen methods for each package to get our totals. foreach ( $calculated_shipping_packages as $key => $package ) { $chosen_method = kkart_get_chosen_shipping_method_for_package( $key, $package ); if ( $chosen_method ) { $chosen_methods[ $key ] = $package['rates'][ $chosen_method ]; } } return $chosen_methods; } /** * Filter items needing shipping callback. * * @since 3.0.0 * @param array $item Item to check for shipping. * @return bool */ protected function filter_items_needing_shipping( $item ) { $product = $item['data']; return $product && $product->needs_shipping(); } /** * Get only items that need shipping. * * @since 3.0.0 * @return array */ protected function get_items_needing_shipping() { return array_filter( $this->get_cart(), array( $this, 'filter_items_needing_shipping' ) ); } /** * Get packages to calculate shipping for. * * This lets us calculate costs for carts that are shipped to multiple locations. * * Shipping methods are responsible for looping through these packages. * * By default we pass the cart itself as a package - plugins can change this. * through the filter and break it up. * * @since 1.5.4 * @return array of cart items */ public function get_shipping_packages() { return apply_filters( 'kkart_cart_shipping_packages', array( array( 'contents' => $this->get_items_needing_shipping(), 'contents_cost' => array_sum( wp_list_pluck( $this->get_items_needing_shipping(), 'line_total' ) ), 'applied_coupons' => $this->get_applied_coupons(), 'user' => array( 'ID' => get_current_user_id(), ), 'destination' => array( 'country' => $this->get_customer()->get_shipping_country(), 'state' => $this->get_customer()->get_shipping_state(), 'postcode' => $this->get_customer()->get_shipping_postcode(), 'city' => $this->get_customer()->get_shipping_city(), 'address' => $this->get_customer()->get_shipping_address(), 'address_1' => $this->get_customer()->get_shipping_address(), // Provide both address and address_1 for backwards compatibility. 'address_2' => $this->get_customer()->get_shipping_address_2(), ), 'cart_subtotal' => $this->get_displayed_subtotal(), ), ) ); } /** * Looks through the cart to see if shipping is actually required. * * @return bool whether or not the cart needs shipping */ public function needs_shipping() { if ( ! kkart_shipping_enabled() || 0 === kkart_get_shipping_method_count( true ) ) { return false; } $needs_shipping = false; foreach ( $this->get_cart_contents() as $cart_item_key => $values ) { if ( $values['data']->needs_shipping() ) { $needs_shipping = true; break; } } return apply_filters( 'kkart_cart_needs_shipping', $needs_shipping ); } /** * Should the shipping address form be shown. * * @return bool */ public function needs_shipping_address() { return apply_filters( 'kkart_cart_needs_shipping_address', true === $this->needs_shipping() && ! kkart_ship_to_billing_address_only() ); } /** * Sees if the customer has entered enough data to calc the shipping yet. * * @return bool */ public function show_shipping() { if ( ! kkart_shipping_enabled() || ! $this->get_cart_contents() ) { return false; } if ( 'yes' === get_option( 'kkart_shipping_cost_requires_address' ) ) { $country = $this->get_customer()->get_shipping_country(); if ( ! $country ) { return false; } $country_fields = KKART()->countries->get_address_fields( $country, 'shipping_' ); if ( isset( $country_fields['shipping_state'] ) && $country_fields['shipping_state']['required'] && ! $this->get_customer()->get_shipping_state() ) { return false; } if ( isset( $country_fields['shipping_postcode'] ) && $country_fields['shipping_postcode']['required'] && ! $this->get_customer()->get_shipping_postcode() ) { return false; } } return apply_filters( 'kkart_cart_ready_to_calc_shipping', true ); } /** * Gets the shipping total (after calculation). * * @return string price or string for the shipping total */ public function get_cart_shipping_total() { // Default total assumes Free shipping. $total = __( 'Free!', 'kkart' ); if ( 0 < $this->get_shipping_total() ) { if ( $this->display_prices_including_tax() ) { $total = kkart_price( $this->shipping_total + $this->shipping_tax_total ); if ( $this->shipping_tax_total > 0 && ! kkart_prices_include_tax() ) { $total .= ' ' . KKART()->countries->inc_tax_or_vat() . ''; } } else { $total = kkart_price( $this->shipping_total ); if ( $this->shipping_tax_total > 0 && kkart_prices_include_tax() ) { $total .= ' ' . KKART()->countries->ex_tax_or_vat() . ''; } } } return apply_filters( 'kkart_cart_shipping_total', $total, $this ); } /** * Check for user coupons (now that we have billing email). If a coupon is invalid, add an error. * * Checks two types of coupons: * 1. Where a list of customer emails are set (limits coupon usage to those defined). * 2. Where a usage_limit_per_user is set (limits coupon usage to a number based on user ID and email). * * @param array $posted Post data. */ public function check_customer_coupons( $posted ) { foreach ( $this->get_applied_coupons() as $code ) { $coupon = new KKART_Coupon( $code ); if ( $coupon->is_valid() ) { // Get user and posted emails to compare. $current_user = wp_get_current_user(); $billing_email = isset( $posted['billing_email'] ) ? $posted['billing_email'] : ''; $check_emails = array_unique( array_filter( array_map( 'strtolower', array_map( 'sanitize_email', array( $billing_email, $current_user->user_email, ) ) ) ) ); // Limit to defined email addresses. $restrictions = $coupon->get_email_restrictions(); if ( is_array( $restrictions ) && 0 < count( $restrictions ) && ! $this->is_coupon_emails_allowed( $check_emails, $restrictions ) ) { $coupon->add_coupon_message( KKART_Coupon::E_KKART_COUPON_NOT_YOURS_REMOVED ); $this->remove_coupon( $code ); } $coupon_usage_limit = $coupon->get_usage_limit_per_user(); if ( 0 < $coupon_usage_limit && 0 === get_current_user_id() ) { // For guest, usage per user has not been enforced yet. Enforce it now. $coupon_data_store = $coupon->get_data_store(); $billing_email = strtolower( sanitize_email( $billing_email ) ); if ( $coupon_data_store && $coupon_data_store->get_usage_by_email( $coupon, $billing_email ) >= $coupon_usage_limit ) { $coupon->add_coupon_message( KKART_Coupon::E_KKART_COUPON_USAGE_LIMIT_REACHED ); } } } } } /** * Checks if the given email address(es) matches the ones specified on the coupon. * * @param array $check_emails Array of customer email addresses. * @param array $restrictions Array of allowed email addresses. * @return bool */ public function is_coupon_emails_allowed( $check_emails, $restrictions ) { foreach ( $check_emails as $check_email ) { // With a direct match we return true. if ( in_array( $check_email, $restrictions, true ) ) { return true; } // Go through the allowed emails and return true if the email matches a wildcard. foreach ( $restrictions as $restriction ) { // Convert to PHP-regex syntax. $regex = '/^' . str_replace( '*', '(.+)?', $restriction ) . '$/'; preg_match( $regex, $check_email, $match ); if ( ! empty( $match ) ) { return true; } } } // No matches, this one isn't allowed. return false; } /** * Returns whether or not a discount has been applied. * * @param string $coupon_code Coupon code to check. * @return bool */ public function has_discount( $coupon_code = '' ) { return $coupon_code ? in_array( kkart_format_coupon_code( $coupon_code ), $this->applied_coupons, true ) : count( $this->applied_coupons ) > 0; } /** * Applies a coupon code passed to the method. * * @param string $coupon_code - The code to apply. * @return bool True if the coupon is applied, false if it does not exist or cannot be applied. */ public function apply_coupon( $coupon_code ) { // Coupons are globally disabled. if ( ! kkart_coupons_enabled() ) { return false; } // Sanitize coupon code. $coupon_code = kkart_format_coupon_code( $coupon_code ); // Get the coupon. $the_coupon = new KKART_Coupon( $coupon_code ); // Prevent adding coupons by post ID. if ( $the_coupon->get_code() !== $coupon_code ) { $the_coupon->set_code( $coupon_code ); $the_coupon->add_coupon_message( KKART_Coupon::E_KKART_COUPON_NOT_EXIST ); return false; } // Check it can be used with cart. if ( ! $the_coupon->is_valid() ) { kkart_add_notice( $the_coupon->get_error_message(), 'error' ); return false; } // Check if applied. if ( $this->has_discount( $coupon_code ) ) { $the_coupon->add_coupon_message( KKART_Coupon::E_KKART_COUPON_ALREADY_APPLIED ); return false; } // If its individual use then remove other coupons. if ( $the_coupon->get_individual_use() ) { $coupons_to_keep = apply_filters( 'kkart_apply_individual_use_coupon', array(), $the_coupon, $this->applied_coupons ); foreach ( $this->applied_coupons as $applied_coupon ) { $keep_key = array_search( $applied_coupon, $coupons_to_keep, true ); if ( false === $keep_key ) { $this->remove_coupon( $applied_coupon ); } else { unset( $coupons_to_keep[ $keep_key ] ); } } if ( ! empty( $coupons_to_keep ) ) { $this->applied_coupons += $coupons_to_keep; } } // Check to see if an individual use coupon is set. if ( $this->applied_coupons ) { foreach ( $this->applied_coupons as $code ) { $coupon = new KKART_Coupon( $code ); if ( $coupon->get_individual_use() && false === apply_filters( 'kkart_apply_with_individual_use_coupon', false, $the_coupon, $coupon, $this->applied_coupons ) ) { // Reject new coupon. $coupon->add_coupon_message( KKART_Coupon::E_KKART_COUPON_ALREADY_APPLIED_INDIV_USE_ONLY ); return false; } } } $this->applied_coupons[] = $coupon_code; // Choose free shipping. if ( $the_coupon->get_free_shipping() ) { $packages = KKART()->shipping()->get_packages(); $chosen_shipping_methods = KKART()->session->get( 'chosen_shipping_methods' ); foreach ( $packages as $i => $package ) { $chosen_shipping_methods[ $i ] = 'free_shipping'; } KKART()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods ); } $the_coupon->add_coupon_message( KKART_Coupon::KKART_COUPON_SUCCESS ); do_action( 'kkart_applied_coupon', $coupon_code ); return true; } /** * Get array of applied coupon objects and codes. * * @param null $deprecated No longer used. * @return array of applied coupons */ public function get_coupons( $deprecated = null ) { $coupons = array(); if ( 'order' === $deprecated ) { return $coupons; } foreach ( $this->get_applied_coupons() as $code ) { $coupon = new KKART_Coupon( $code ); $coupons[ $code ] = $coupon; } return $coupons; } /** * Get the discount amount for a used coupon. * * @param string $code coupon code. * @param bool $ex_tax inc or ex tax. * @return float discount amount */ public function get_coupon_discount_amount( $code, $ex_tax = true ) { $totals = $this->get_coupon_discount_totals(); $discount_amount = isset( $totals[ $code ] ) ? $totals[ $code ] : 0; if ( ! $ex_tax ) { $discount_amount += $this->get_coupon_discount_tax_amount( $code ); } return kkart_cart_round_discount( $discount_amount, kkart_get_price_decimals() ); } /** * Get the discount tax amount for a used coupon (for tax inclusive prices). * * @param string $code coupon code. * @return float discount amount */ public function get_coupon_discount_tax_amount( $code ) { $totals = $this->get_coupon_discount_tax_totals(); return kkart_cart_round_discount( isset( $totals[ $code ] ) ? $totals[ $code ] : 0, kkart_get_price_decimals() ); } /** * Remove coupons from the cart of a defined type. Type 1 is before tax, type 2 is after tax. * * @param null $deprecated No longer used. */ public function remove_coupons( $deprecated = null ) { $this->set_coupon_discount_totals( array() ); $this->set_coupon_discount_tax_totals( array() ); $this->set_applied_coupons( array() ); $this->session->set_session(); } /** * Remove a single coupon by code. * * @param string $coupon_code Code of the coupon to remove. * @return bool */ public function remove_coupon( $coupon_code ) { $coupon_code = kkart_format_coupon_code( $coupon_code ); $position = array_search( $coupon_code, array_map( 'kkart_format_coupon_code', $this->get_applied_coupons() ), true ); if ( false !== $position ) { unset( $this->applied_coupons[ $position ] ); } KKART()->session->set( 'refresh_totals', true ); do_action( 'kkart_removed_coupon', $coupon_code ); return true; } /** * Trigger an action so 3rd parties can add custom fees. * * @since 2.0.0 */ public function calculate_fees() { do_action( 'kkart_cart_calculate_fees', $this ); } /** * Return reference to fees API. * * @since 3.2.0 * @return KKART_Cart_Fees */ public function fees_api() { return $this->fees_api; } /** * Add additional fee to the cart. * * This method should be called on a callback attached to the * kkart_cart_calculate_fees action during cart/checkout. Fees do not * persist. * * @uses KKART_Cart_Fees::add_fee * @param string $name Unique name for the fee. Multiple fees of the same name cannot be added. * @param float $amount Fee amount (do not enter negative amounts). * @param bool $taxable Is the fee taxable? (default: false). * @param string $tax_class The tax class for the fee if taxable. A blank string is standard tax class. (default: ''). */ public function add_fee( $name, $amount, $taxable = false, $tax_class = '' ) { $this->fees_api()->add_fee( array( 'name' => $name, 'amount' => (float) $amount, 'taxable' => $taxable, 'tax_class' => $tax_class, ) ); } /** * Return all added fees from the Fees API. * * @uses KKART_Cart_Fees::get_fees * @return array */ public function get_fees() { $fees = $this->fees_api()->get_fees(); if ( property_exists( $this, 'fees' ) ) { $fees = $fees + (array) $this->fees; } return $fees; } /** * Gets the total excluding taxes. * * @return string formatted price */ public function get_total_ex_tax() { return apply_filters( 'kkart_cart_total_ex_tax', kkart_price( max( 0, $this->get_total( 'edit' ) - $this->get_total_tax() ) ) ); } /** * Gets the cart contents total (after calculation). * * @return string formatted price */ public function get_cart_total() { return apply_filters( 'kkart_cart_contents_total', kkart_price( kkart_prices_include_tax() ? $this->get_cart_contents_total() + $this->get_cart_contents_tax() : $this->get_cart_contents_total() ) ); } /** * Gets the sub total (after calculation). * * @param bool $compound whether to include compound taxes. * @return string formatted price */ public function get_cart_subtotal( $compound = false ) { /** * If the cart has compound tax, we want to show the subtotal as cart + shipping + non-compound taxes (after discount). */ if ( $compound ) { $cart_subtotal = kkart_price( $this->get_cart_contents_total() + $this->get_shipping_total() + $this->get_taxes_total( false, false ) ); } elseif ( $this->display_prices_including_tax() ) { $cart_subtotal = kkart_price( $this->get_subtotal() + $this->get_subtotal_tax() ); if ( $this->get_subtotal_tax() > 0 && ! kkart_prices_include_tax() ) { $cart_subtotal .= ' ' . KKART()->countries->inc_tax_or_vat() . ''; } } else { $cart_subtotal = kkart_price( $this->get_subtotal() ); if ( $this->get_subtotal_tax() > 0 && kkart_prices_include_tax() ) { $cart_subtotal .= ' ' . KKART()->countries->ex_tax_or_vat() . ''; } } return apply_filters( 'kkart_cart_subtotal', $cart_subtotal, $compound, $this ); } /** * Get the product row price per item. * * @param KKART_Product $product Product object. * @return string formatted price */ public function get_product_price( $product ) { if ( $this->display_prices_including_tax() ) { $product_price = kkart_get_price_including_tax( $product ); } else { $product_price = kkart_get_price_excluding_tax( $product ); } return apply_filters( 'kkart_cart_product_price', kkart_price( $product_price ), $product ); } /** * Get the product row subtotal. * * Gets the tax etc to avoid rounding issues. * * When on the checkout (review order), this will get the subtotal based on the customer's tax rate rather than the base rate. * * @param KKART_Product $product Product object. * @param int $quantity Quantity being purchased. * @return string formatted price */ public function get_product_subtotal( $product, $quantity ) { $price = $product->get_price(); if ( $product->is_taxable() ) { if ( $this->display_prices_including_tax() ) { $row_price = kkart_get_price_including_tax( $product, array( 'qty' => $quantity ) ); $product_subtotal = kkart_price( $row_price ); if ( ! kkart_prices_include_tax() && $this->get_subtotal_tax() > 0 ) { $product_subtotal .= ' ' . KKART()->countries->inc_tax_or_vat() . ''; } } else { $row_price = kkart_get_price_excluding_tax( $product, array( 'qty' => $quantity ) ); $product_subtotal = kkart_price( $row_price ); if ( kkart_prices_include_tax() && $this->get_subtotal_tax() > 0 ) { $product_subtotal .= ' ' . KKART()->countries->ex_tax_or_vat() . ''; } } } else { $row_price = $price * $quantity; $product_subtotal = kkart_price( $row_price ); } return apply_filters( 'kkart_cart_product_subtotal', $product_subtotal, $product, $quantity, $this ); } /** * Gets the cart tax (after calculation). * * @return string formatted price */ public function get_cart_tax() { $cart_total_tax = kkart_round_tax_total( $this->get_cart_contents_tax() + $this->get_shipping_tax() + $this->get_fee_tax() ); return apply_filters( 'kkart_get_cart_tax', $cart_total_tax ? kkart_price( $cart_total_tax ) : '' ); } /** * Get a tax amount. * * @param string $tax_rate_id ID of the tax rate to get taxes for. * @return float amount */ public function get_tax_amount( $tax_rate_id ) { $taxes = kkart_array_merge_recursive_numeric( $this->get_cart_contents_taxes(), $this->get_fee_taxes() ); return isset( $taxes[ $tax_rate_id ] ) ? $taxes[ $tax_rate_id ] : 0; } /** * Get a tax amount. * * @param string $tax_rate_id ID of the tax rate to get taxes for. * @return float amount */ public function get_shipping_tax_amount( $tax_rate_id ) { $taxes = $this->get_shipping_taxes(); return isset( $taxes[ $tax_rate_id ] ) ? $taxes[ $tax_rate_id ] : 0; } /** * Get tax row amounts with or without compound taxes includes. * * @param bool $compound True if getting compound taxes. * @param bool $display True if getting total to display. * @return float price */ public function get_taxes_total( $compound = true, $display = true ) { $total = 0; $taxes = $this->get_taxes(); foreach ( $taxes as $key => $tax ) { if ( ! $compound && KKART_Tax::is_compound( $key ) ) { continue; } $total += $tax; } if ( $display ) { $total = kkart_format_decimal( $total, kkart_get_price_decimals() ); } return apply_filters( 'kkart_cart_taxes_total', $total, $compound, $display, $this ); } /** * Gets the total discount amount. * * @return mixed formatted price or false if there are none */ public function get_total_discount() { return apply_filters( 'kkart_cart_total_discount', $this->get_discount_total() ? kkart_price( $this->get_discount_total() ) : false, $this ); } /** * Reset cart totals to the defaults. Useful before running calculations. */ private function reset_totals() { $this->totals = $this->default_totals; $this->fees_api->remove_all_fees(); do_action( 'kkart_cart_reset', $this, false ); } /** * Returns 'incl' if tax should be included in cart, otherwise returns 'excl'. * * @return string */ public function get_tax_price_display_mode() { if ( $this->get_customer() && $this->get_customer()->get_is_vat_exempt() ) { return 'excl'; } return get_option( 'kkart_tax_display_cart' ); } /** * Returns the hash based on cart contents. * * @since 3.6.0 * @return string hash for cart content */ public function get_cart_hash() { $cart_session = $this->session->get_cart_for_session(); $hash = $cart_session ? md5( wp_json_encode( $cart_session ) . $this->get_total( 'edit' ) ) : ''; $hash = apply_filters_deprecated( 'kkart_add_to_cart_hash', array( $hash, $cart_session ), '3.6.0', 'kkart_cart_hash' ); return apply_filters( 'kkart_cart_hash', $hash, $cart_session ); } } PK!)f zz+import/class-kkart-product-csv-importer.phpnu[ 0, // File pointer start. 'end_pos' => -1, // File pointer end. 'lines' => -1, // Max lines to read. 'mapping' => array(), // Column mapping. csv_heading => schema_heading. 'parse' => false, // Whether to sanitize and format data. 'update_existing' => false, // Whether to update existing items. 'delimiter' => ',', // CSV delimiter. 'prevent_timeouts' => true, // Check memory and time usage and abort if reaching limit. 'enclosure' => '"', // The character used to wrap text in the CSV. 'escape' => "\0", // PHP uses '\' as the default escape character. This is not RFC-4180 compliant. This disables the escape character. ); $this->params = wp_parse_args( $params, $default_args ); $this->file = $file; if ( isset( $this->params['mapping']['from'], $this->params['mapping']['to'] ) ) { $this->params['mapping'] = array_combine( $this->params['mapping']['from'], $this->params['mapping']['to'] ); } // Import mappings for CSV data. include_once dirname( dirname( __FILE__ ) ) . '/admin/importers/mappings/mappings.php'; $this->read_file(); } /** * Read file. */ protected function read_file() { if ( ! KKART_Product_CSV_Importer_Controller::is_file_valid_csv( $this->file ) ) { wp_die( esc_html__( 'Invalid file type. The importer supports CSV and TXT file formats.', 'kkart' ) ); } $handle = fopen( $this->file, 'r' ); // @codingStandardsIgnoreLine. if ( false !== $handle ) { $this->raw_keys = version_compare( PHP_VERSION, '5.3', '>=' ) ? array_map( 'trim', fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ) ) : array_map( 'trim', fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] ) ); // @codingStandardsIgnoreLine // Remove BOM signature from the first item. if ( isset( $this->raw_keys[0] ) ) { $this->raw_keys[0] = $this->remove_utf8_bom( $this->raw_keys[0] ); } if ( 0 !== $this->params['start_pos'] ) { fseek( $handle, (int) $this->params['start_pos'] ); } while ( 1 ) { $row = version_compare( PHP_VERSION, '5.3', '>=' ) ? fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'], $this->params['escape'] ) : fgetcsv( $handle, 0, $this->params['delimiter'], $this->params['enclosure'] ); // @codingStandardsIgnoreLine if ( false !== $row ) { $this->raw_data[] = $row; $this->file_positions[ count( $this->raw_data ) ] = ftell( $handle ); if ( ( $this->params['end_pos'] > 0 && ftell( $handle ) >= $this->params['end_pos'] ) || 0 === --$this->params['lines'] ) { break; } } else { break; } } $this->file_position = ftell( $handle ); } if ( ! empty( $this->params['mapping'] ) ) { $this->set_mapped_keys(); } if ( $this->params['parse'] ) { $this->set_parsed_data(); } } /** * Remove UTF-8 BOM signature. * * @param string $string String to handle. * * @return string */ protected function remove_utf8_bom( $string ) { if ( 'efbbbf' === substr( bin2hex( $string ), 0, 6 ) ) { $string = substr( $string, 3 ); } return $string; } /** * Set file mapped keys. */ protected function set_mapped_keys() { $mapping = $this->params['mapping']; foreach ( $this->raw_keys as $key ) { $this->mapped_keys[] = isset( $mapping[ $key ] ) ? $mapping[ $key ] : $key; } } /** * Parse relative field and return product ID. * * Handles `id:xx` and SKUs. * * If mapping to an id: and the product ID does not exist, this link is not * valid. * * If mapping to a SKU and the product ID does not exist, a temporary object * will be created so it can be updated later. * * @param string $value Field value. * * @return int|string */ public function parse_relative_field( $value ) { global $wpdb; if ( empty( $value ) ) { return ''; } // IDs are prefixed with id:. if ( preg_match( '/^id:(\d+)$/', $value, $matches ) ) { $id = intval( $matches[1] ); // If original_id is found, use that instead of the given ID since a new placeholder must have been created already. $original_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_original_id' AND meta_value = %s;", $id ) ); // WPCS: db call ok, cache ok. if ( $original_id ) { return absint( $original_id ); } // See if the given ID maps to a valid product allready. $existing_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type IN ( 'product', 'product_variation' ) AND ID = %d;", $id ) ); // WPCS: db call ok, cache ok. if ( $existing_id ) { return absint( $existing_id ); } // If we're not updating existing posts, we may need a placeholder product to map to. if ( ! $this->params['update_existing'] ) { $product = kkart_get_product_object( 'simple' ); $product->set_name( 'Import placeholder for ' . $id ); $product->set_status( 'importing' ); $product->add_meta_data( '_original_id', $id, true ); $id = $product->save(); } return $id; } $id = kkart_get_product_id_by_sku( $value ); if ( $id ) { return $id; } try { $product = kkart_get_product_object( 'simple' ); $product->set_name( 'Import placeholder for ' . $value ); $product->set_status( 'importing' ); $product->set_sku( $value ); $id = $product->save(); if ( $id && ! is_wp_error( $id ) ) { return $id; } } catch ( Exception $e ) { return ''; } return ''; } /** * Parse the ID field. * * If we're not doing an update, create a placeholder product so mapping works * for rows following this one. * * @param string $value Field value. * * @return int */ public function parse_id_field( $value ) { global $wpdb; $id = absint( $value ); if ( ! $id ) { return 0; } // See if this maps to an ID placeholder already. $original_id = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '_original_id' AND meta_value = %s;", $id ) ); // WPCS: db call ok, cache ok. if ( $original_id ) { return absint( $original_id ); } // Not updating? Make sure we have a new placeholder for this ID. if ( ! $this->params['update_existing'] ) { $mapped_keys = $this->get_mapped_keys(); $sku_column_index = absint( array_search( 'sku', $mapped_keys, true ) ); $row_sku = isset( $this->raw_data[ $this->parsing_raw_data_index ][ $sku_column_index ] ) ? $this->raw_data[ $this->parsing_raw_data_index ][ $sku_column_index ] : ''; $id_from_sku = $row_sku ? kkart_get_product_id_by_sku( $row_sku ) : ''; // If row has a SKU, make sure placeholder was not made already. if ( $id_from_sku ) { return $id_from_sku; } $product = kkart_get_product_object( 'simple' ); $product->set_name( 'Import placeholder for ' . $id ); $product->set_status( 'importing' ); $product->add_meta_data( '_original_id', $id, true ); // If row has a SKU, make sure placeholder has it too. if ( $row_sku ) { $product->set_sku( $row_sku ); } $id = $product->save(); } return $id && ! is_wp_error( $id ) ? $id : 0; } /** * Parse relative comma-delineated field and return product ID. * * @param string $value Field value. * * @return array */ public function parse_relative_comma_field( $value ) { if ( empty( $value ) ) { return array(); } return array_filter( array_map( array( $this, 'parse_relative_field' ), $this->explode_values( $value ) ) ); } /** * Parse a comma-delineated field from a CSV. * * @param string $value Field value. * * @return array */ public function parse_comma_field( $value ) { if ( empty( $value ) && '0' !== $value ) { return array(); } $value = $this->unescape_data( $value ); return array_map( 'kkart_clean', $this->explode_values( $value ) ); } /** * Parse a field that is generally '1' or '0' but can be something else. * * @param string $value Field value. * * @return bool|string */ public function parse_bool_field( $value ) { if ( '0' === $value ) { return false; } if ( '1' === $value ) { return true; } // Don't return explicit true or false for empty fields or values like 'notify'. return kkart_clean( $value ); } /** * Parse a float value field. * * @param string $value Field value. * * @return float|string */ public function parse_float_field( $value ) { if ( '' === $value ) { return $value; } // Remove the ' prepended to fields that start with - if needed. $value = $this->unescape_data( $value ); return floatval( $value ); } /** * Parse the stock qty field. * * @param string $value Field value. * * @return float|string */ public function parse_stock_quantity_field( $value ) { if ( '' === $value ) { return $value; } // Remove the ' prepended to fields that start with - if needed. $value = $this->unescape_data( $value ); return kkart_stock_amount( $value ); } /** * Parse the tax status field. * * @param string $value Field value. * * @return string */ public function parse_tax_status_field( $value ) { if ( '' === $value ) { return $value; } // Remove the ' prepended to fields that start with - if needed. $value = $this->unescape_data( $value ); if ( 'true' === strtolower( $value ) || 'false' === strtolower( $value ) ) { $value = kkart_string_to_bool( $value ) ? 'taxable' : 'none'; } return kkart_clean( $value ); } /** * Parse a category field from a CSV. * Categories are separated by commas and subcategories are "parent > subcategory". * * @param string $value Field value. * * @return array of arrays with "parent" and "name" keys. */ public function parse_categories_field( $value ) { if ( empty( $value ) ) { return array(); } $row_terms = $this->explode_values( $value ); $categories = array(); foreach ( $row_terms as $row_term ) { $parent = null; $_terms = array_map( 'trim', explode( '>', $row_term ) ); $total = count( $_terms ); foreach ( $_terms as $index => $_term ) { // Don't allow users without capabilities to create new categories. if ( ! current_user_can( 'manage_product_terms' ) ) { break; } $term = wp_insert_term( $_term, 'product_cat', array( 'parent' => intval( $parent ) ) ); if ( is_wp_error( $term ) ) { if ( $term->get_error_code() === 'term_exists' ) { // When term exists, error data should contain existing term id. $term_id = $term->get_error_data(); } else { break; // We cannot continue on any other error. } } else { // New term. $term_id = $term['term_id']; } // Only requires assign the last category. if ( ( 1 + $index ) === $total ) { $categories[] = $term_id; } else { // Store parent to be able to insert or query categories based in parent ID. $parent = $term_id; } } } return $categories; } /** * Parse a tag field from a CSV. * * @param string $value Field value. * * @return array */ public function parse_tags_field( $value ) { if ( empty( $value ) ) { return array(); } $value = $this->unescape_data( $value ); $names = $this->explode_values( $value ); $tags = array(); foreach ( $names as $name ) { $term = get_term_by( 'name', $name, 'product_tag' ); if ( ! $term || is_wp_error( $term ) ) { $term = (object) wp_insert_term( $name, 'product_tag' ); } if ( ! is_wp_error( $term ) ) { $tags[] = $term->term_id; } } return $tags; } /** * Parse a tag field from a CSV with space separators. * * @param string $value Field value. * * @return array */ public function parse_tags_spaces_field( $value ) { if ( empty( $value ) ) { return array(); } $value = $this->unescape_data( $value ); $names = $this->explode_values( $value, ' ' ); $tags = array(); foreach ( $names as $name ) { $term = get_term_by( 'name', $name, 'product_tag' ); if ( ! $term || is_wp_error( $term ) ) { $term = (object) wp_insert_term( $name, 'product_tag' ); } if ( ! is_wp_error( $term ) ) { $tags[] = $term->term_id; } } return $tags; } /** * Parse a shipping class field from a CSV. * * @param string $value Field value. * * @return int */ public function parse_shipping_class_field( $value ) { if ( empty( $value ) ) { return 0; } $term = get_term_by( 'name', $value, 'product_shipping_class' ); if ( ! $term || is_wp_error( $term ) ) { $term = (object) wp_insert_term( $value, 'product_shipping_class' ); } if ( is_wp_error( $term ) ) { return 0; } return $term->term_id; } /** * Parse images list from a CSV. Images can be filenames or URLs. * * @param string $value Field value. * * @return array */ public function parse_images_field( $value ) { if ( empty( $value ) ) { return array(); } $images = array(); $separator = apply_filters( 'kkart_product_import_image_separator', ',' ); foreach ( $this->explode_values( $value, $separator ) as $image ) { if ( stristr( $image, '://' ) ) { $images[] = esc_url_raw( $image ); } else { $images[] = sanitize_file_name( $image ); } } return $images; } /** * Parse dates from a CSV. * Dates requires the format YYYY-MM-DD and time is optional. * * @param string $value Field value. * * @return string|null */ public function parse_date_field( $value ) { if ( empty( $value ) ) { return null; } if ( preg_match( '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])([ 01-9:]*)$/', $value ) ) { // Don't include the time if the field had time in it. return current( explode( ' ', $value ) ); } return null; } /** * Parse backorders from a CSV. * * @param string $value Field value. * * @return string */ public function parse_backorders_field( $value ) { if ( empty( $value ) ) { return 'no'; } $value = $this->parse_bool_field( $value ); if ( 'notify' === $value ) { return 'notify'; } elseif ( is_bool( $value ) ) { return $value ? 'yes' : 'no'; } return 'no'; } /** * Just skip current field. * * By default is applied kkart_clean() to all not listed fields * in self::get_formatting_callback(), use this method to skip any formatting. * * @param string $value Field value. * * @return string */ public function parse_skip_field( $value ) { return $value; } /** * Parse download file urls, we should allow shortcodes here. * * Allow shortcodes if present, othersiwe esc_url the value. * * @param string $value Field value. * * @return string */ public function parse_download_file_field( $value ) { // Absolute file paths. if ( 0 === strpos( $value, 'http' ) ) { return esc_url_raw( $value ); } // Relative and shortcode paths. return kkart_clean( $value ); } /** * Parse an int value field * * @param int $value field value. * * @return int */ public function parse_int_field( $value ) { // Remove the ' prepended to fields that start with - if needed. $value = $this->unescape_data( $value ); return intval( $value ); } /** * Parse a description value field * * @param string $description field value. * * @return string */ public function parse_description_field( $description ) { $parts = explode( "\\\\n", $description ); foreach ( $parts as $key => $part ) { $parts[ $key ] = str_replace( '\n', "\n", $part ); } return implode( '\\\n', $parts ); } /** * Parse the published field. 1 is published, 0 is private, -1 is draft. * Alternatively, 'true' can be used for published and 'false' for draft. * * @param string $value Field value. * * @return float|string */ public function parse_published_field( $value ) { if ( '' === $value ) { return $value; } // Remove the ' prepended to fields that start with - if needed. $value = $this->unescape_data( $value ); if ( 'true' === strtolower( $value ) || 'false' === strtolower( $value ) ) { return kkart_string_to_bool( $value ) ? 1 : -1; } return floatval( $value ); } /** * Deprecated get formatting callback method. * * @deprecated 4.3.0 * @return array */ protected function get_formating_callback() { return $this->get_formatting_callback(); } /** * Get formatting callback. * * @since 4.3.0 * @return array */ protected function get_formatting_callback() { /** * Columns not mentioned here will get parsed with 'kkart_clean'. * column_name => callback. */ $data_formatting = array( 'id' => array( $this, 'parse_id_field' ), 'type' => array( $this, 'parse_comma_field' ), 'published' => array( $this, 'parse_published_field' ), 'featured' => array( $this, 'parse_bool_field' ), 'date_on_sale_from' => array( $this, 'parse_date_field' ), 'date_on_sale_to' => array( $this, 'parse_date_field' ), 'name' => array( $this, 'parse_skip_field' ), 'short_description' => array( $this, 'parse_description_field' ), 'description' => array( $this, 'parse_description_field' ), 'manage_stock' => array( $this, 'parse_bool_field' ), 'low_stock_amount' => array( $this, 'parse_stock_quantity_field' ), 'backorders' => array( $this, 'parse_backorders_field' ), 'stock_status' => array( $this, 'parse_bool_field' ), 'sold_individually' => array( $this, 'parse_bool_field' ), 'width' => array( $this, 'parse_float_field' ), 'length' => array( $this, 'parse_float_field' ), 'height' => array( $this, 'parse_float_field' ), 'weight' => array( $this, 'parse_float_field' ), 'reviews_allowed' => array( $this, 'parse_bool_field' ), 'purchase_note' => 'wp_filter_post_kses', 'price' => 'kkart_format_decimal', 'regular_price' => 'kkart_format_decimal', 'stock_quantity' => array( $this, 'parse_stock_quantity_field' ), 'category_ids' => array( $this, 'parse_categories_field' ), 'tag_ids' => array( $this, 'parse_tags_field' ), 'tag_ids_spaces' => array( $this, 'parse_tags_spaces_field' ), 'shipping_class_id' => array( $this, 'parse_shipping_class_field' ), 'images' => array( $this, 'parse_images_field' ), 'parent_id' => array( $this, 'parse_relative_field' ), 'grouped_products' => array( $this, 'parse_relative_comma_field' ), 'upsell_ids' => array( $this, 'parse_relative_comma_field' ), 'cross_sell_ids' => array( $this, 'parse_relative_comma_field' ), 'download_limit' => array( $this, 'parse_int_field' ), 'download_expiry' => array( $this, 'parse_int_field' ), 'product_url' => 'esc_url_raw', 'menu_order' => 'intval', 'tax_status' => array( $this, 'parse_tax_status_field' ), ); /** * Match special column names. */ $regex_match_data_formatting = array( '/attributes:value*/' => array( $this, 'parse_comma_field' ), '/attributes:visible*/' => array( $this, 'parse_bool_field' ), '/attributes:taxonomy*/' => array( $this, 'parse_bool_field' ), '/downloads:url*/' => array( $this, 'parse_download_file_field' ), '/meta:*/' => 'wp_kses_post', // Allow some HTML in meta fields. ); $callbacks = array(); // Figure out the parse function for each column. foreach ( $this->get_mapped_keys() as $index => $heading ) { $callback = 'kkart_clean'; if ( isset( $data_formatting[ $heading ] ) ) { $callback = $data_formatting[ $heading ]; } else { foreach ( $regex_match_data_formatting as $regex => $callback ) { if ( preg_match( $regex, $heading ) ) { $callback = $callback; break; } } } $callbacks[] = $callback; } return apply_filters( 'kkart_product_importer_formatting_callbacks', $callbacks, $this ); } /** * Check if strings starts with determined word. * * @param string $haystack Complete sentence. * @param string $needle Excerpt. * * @return bool */ protected function starts_with( $haystack, $needle ) { return substr( $haystack, 0, strlen( $needle ) ) === $needle; } /** * Expand special and internal data into the correct formats for the product CRUD. * * @param array $data Data to import. * * @return array */ protected function expand_data( $data ) { $data = apply_filters( 'kkart_product_importer_pre_expand_data', $data ); // Images field maps to image and gallery id fields. if ( isset( $data['images'] ) ) { $images = $data['images']; $data['raw_image_id'] = array_shift( $images ); if ( ! empty( $images ) ) { $data['raw_gallery_image_ids'] = $images; } unset( $data['images'] ); } // Type, virtual and downloadable are all stored in the same column. if ( isset( $data['type'] ) ) { $data['type'] = array_map( 'strtolower', $data['type'] ); $data['virtual'] = in_array( 'virtual', $data['type'], true ); $data['downloadable'] = in_array( 'downloadable', $data['type'], true ); // Convert type to string. $data['type'] = current( array_diff( $data['type'], array( 'virtual', 'downloadable' ) ) ); if ( ! $data['type'] ) { $data['type'] = 'simple'; } } // Status is mapped from a special published field. if ( isset( $data['published'] ) ) { $statuses = array( -1 => 'draft', 0 => 'private', 1 => 'publish', ); $data['status'] = isset( $statuses[ $data['published'] ] ) ? $statuses[ $data['published'] ] : 'draft'; // Fix draft status of variations. if ( isset( $data['type'] ) && 'variation' === $data['type'] && -1 === $data['published'] ) { $data['status'] = 'publish'; } unset( $data['published'] ); } if ( isset( $data['stock_quantity'] ) ) { if ( '' === $data['stock_quantity'] ) { $data['manage_stock'] = false; $data['stock_status'] = isset( $data['stock_status'] ) ? $data['stock_status'] : true; } else { $data['manage_stock'] = true; } } // Stock is bool or 'backorder'. if ( isset( $data['stock_status'] ) ) { if ( 'backorder' === $data['stock_status'] ) { $data['stock_status'] = 'onbackorder'; } else { $data['stock_status'] = $data['stock_status'] ? 'instock' : 'outofstock'; } } // Prepare grouped products. if ( isset( $data['grouped_products'] ) ) { $data['children'] = $data['grouped_products']; unset( $data['grouped_products'] ); } // Tag ids. if ( isset( $data['tag_ids_spaces'] ) ) { $data['tag_ids'] = $data['tag_ids_spaces']; unset( $data['tag_ids_spaces'] ); } // Handle special column names which span multiple columns. $attributes = array(); $downloads = array(); $meta_data = array(); foreach ( $data as $key => $value ) { if ( $this->starts_with( $key, 'attributes:name' ) ) { if ( ! empty( $value ) ) { $attributes[ str_replace( 'attributes:name', '', $key ) ]['name'] = $value; } unset( $data[ $key ] ); } elseif ( $this->starts_with( $key, 'attributes:value' ) ) { $attributes[ str_replace( 'attributes:value', '', $key ) ]['value'] = $value; unset( $data[ $key ] ); } elseif ( $this->starts_with( $key, 'attributes:taxonomy' ) ) { $attributes[ str_replace( 'attributes:taxonomy', '', $key ) ]['taxonomy'] = kkart_string_to_bool( $value ); unset( $data[ $key ] ); } elseif ( $this->starts_with( $key, 'attributes:visible' ) ) { $attributes[ str_replace( 'attributes:visible', '', $key ) ]['visible'] = kkart_string_to_bool( $value ); unset( $data[ $key ] ); } elseif ( $this->starts_with( $key, 'attributes:default' ) ) { if ( ! empty( $value ) ) { $attributes[ str_replace( 'attributes:default', '', $key ) ]['default'] = $value; } unset( $data[ $key ] ); } elseif ( $this->starts_with( $key, 'downloads:name' ) ) { if ( ! empty( $value ) ) { $downloads[ str_replace( 'downloads:name', '', $key ) ]['name'] = $value; } unset( $data[ $key ] ); } elseif ( $this->starts_with( $key, 'downloads:url' ) ) { if ( ! empty( $value ) ) { $downloads[ str_replace( 'downloads:url', '', $key ) ]['url'] = $value; } unset( $data[ $key ] ); } elseif ( $this->starts_with( $key, 'meta:' ) ) { $meta_data[] = array( 'key' => str_replace( 'meta:', '', $key ), 'value' => $value, ); unset( $data[ $key ] ); } } if ( ! empty( $attributes ) ) { // Remove empty attributes and clear indexes. foreach ( $attributes as $attribute ) { if ( empty( $attribute['name'] ) ) { continue; } $data['raw_attributes'][] = $attribute; } } if ( ! empty( $downloads ) ) { $data['downloads'] = array(); foreach ( $downloads as $key => $file ) { if ( empty( $file['url'] ) ) { continue; } $data['downloads'][] = array( 'name' => $file['name'] ? $file['name'] : kkart_get_filename_from_url( $file['url'] ), 'file' => $file['url'], ); } } if ( ! empty( $meta_data ) ) { $data['meta_data'] = $meta_data; } return $data; } /** * Map and format raw data to known fields. */ protected function set_parsed_data() { $parse_functions = $this->get_formatting_callback(); $mapped_keys = $this->get_mapped_keys(); $use_mb = function_exists( 'mb_convert_encoding' ); // Parse the data. foreach ( $this->raw_data as $row_index => $row ) { // Skip empty rows. if ( ! count( array_filter( $row ) ) ) { continue; } $this->parsing_raw_data_index = $row_index; $data = array(); do_action( 'kkart_product_importer_before_set_parsed_data', $row, $mapped_keys ); foreach ( $row as $id => $value ) { // Skip ignored columns. if ( empty( $mapped_keys[ $id ] ) ) { continue; } // Convert UTF8. if ( $use_mb ) { $encoding = mb_detect_encoding( $value, mb_detect_order(), true ); if ( $encoding ) { $value = mb_convert_encoding( $value, 'UTF-8', $encoding ); } else { $value = mb_convert_encoding( $value, 'UTF-8', 'UTF-8' ); } } else { $value = wp_check_invalid_utf8( $value, true ); } $data[ $mapped_keys[ $id ] ] = call_user_func( $parse_functions[ $id ], $value ); } /** * Filter product importer parsed data. * * @param array $parsed_data Parsed data. * @param KKART_Product_Importer $importer Importer instance. */ $this->parsed_data[] = apply_filters( 'kkart_product_importer_parsed_data', $this->expand_data( $data ), $this ); } } /** * Get a string to identify the row from parsed data. * * @param array $parsed_data Parsed data. * * @return string */ protected function get_row_id( $parsed_data ) { $id = isset( $parsed_data['id'] ) ? absint( $parsed_data['id'] ) : 0; $sku = isset( $parsed_data['sku'] ) ? esc_attr( $parsed_data['sku'] ) : ''; $name = isset( $parsed_data['name'] ) ? esc_attr( $parsed_data['name'] ) : ''; $row_data = array(); if ( $name ) { $row_data[] = $name; } if ( $id ) { /* translators: %d: product ID */ $row_data[] = sprintf( __( 'ID %d', 'kkart' ), $id ); } if ( $sku ) { /* translators: %s: product SKU */ $row_data[] = sprintf( __( 'SKU %s', 'kkart' ), $sku ); } return implode( ', ', $row_data ); } /** * Process importer. * * Do not import products with IDs or SKUs that already exist if option * update existing is false, and likewise, if updating products, do not * process rows which do not exist if an ID/SKU is provided. * * @return array */ public function import() { $this->start_time = time(); $index = 0; $update_existing = $this->params['update_existing']; $data = array( 'imported' => array(), 'failed' => array(), 'updated' => array(), 'skipped' => array(), ); foreach ( $this->parsed_data as $parsed_data_key => $parsed_data ) { do_action( 'kkart_product_import_before_import', $parsed_data ); $id = isset( $parsed_data['id'] ) ? absint( $parsed_data['id'] ) : 0; $sku = isset( $parsed_data['sku'] ) ? $parsed_data['sku'] : ''; $id_exists = false; $sku_exists = false; if ( $id ) { $product = kkart_get_product( $id ); $id_exists = $product && 'importing' !== $product->get_status(); } if ( $sku ) { $id_from_sku = kkart_get_product_id_by_sku( $sku ); $product = $id_from_sku ? kkart_get_product( $id_from_sku ) : false; $sku_exists = $product && 'importing' !== $product->get_status(); } if ( $id_exists && ! $update_existing ) { $data['skipped'][] = new WP_Error( 'kkart_product_importer_error', esc_html__( 'A product with this ID already exists.', 'kkart' ), array( 'id' => $id, 'row' => $this->get_row_id( $parsed_data ), ) ); continue; } if ( $sku_exists && ! $update_existing ) { $data['skipped'][] = new WP_Error( 'kkart_product_importer_error', esc_html__( 'A product with this SKU already exists.', 'kkart' ), array( 'sku' => esc_attr( $sku ), 'row' => $this->get_row_id( $parsed_data ), ) ); continue; } if ( $update_existing && ( isset( $parsed_data['id'] ) || isset( $parsed_data['sku'] ) ) && ! $id_exists && ! $sku_exists ) { $data['skipped'][] = new WP_Error( 'kkart_product_importer_error', esc_html__( 'No matching product exists to update.', 'kkart' ), array( 'id' => $id, 'sku' => esc_attr( $sku ), 'row' => $this->get_row_id( $parsed_data ), ) ); continue; } $result = $this->process_item( $parsed_data ); if ( is_wp_error( $result ) ) { $result->add_data( array( 'row' => $this->get_row_id( $parsed_data ) ) ); $data['failed'][] = $result; } elseif ( $result['updated'] ) { $data['updated'][] = $result['id']; } else { $data['imported'][] = $result['id']; } $index ++; if ( $this->params['prevent_timeouts'] && ( $this->time_exceeded() || $this->memory_exceeded() ) ) { $this->file_position = $this->file_positions[ $index ]; break; } } return $data; } } PK!:˜WW*import/abstract-kkart-product-importer.phpnu[raw_keys; } /** * Get file mapped headers. * * @return array */ public function get_mapped_keys() { return ! empty( $this->mapped_keys ) ? $this->mapped_keys : $this->raw_keys; } /** * Get raw data. * * @return array */ public function get_raw_data() { return $this->raw_data; } /** * Get parsed data. * * @return array */ public function get_parsed_data() { /** * Filter product importer parsed data. * * @param array $parsed_data Parsed data. * @param KKART_Product_Importer $importer Importer instance. */ return apply_filters( 'kkart_product_importer_parsed_data', $this->parsed_data, $this ); } /** * Get importer parameters. * * @return array */ public function get_params() { return $this->params; } /** * Get file pointer position from the last read. * * @return int */ public function get_file_position() { return $this->file_position; } /** * Get file pointer position as a percentage of file size. * * @return int */ public function get_percent_complete() { $size = filesize( $this->file ); if ( ! $size ) { return 0; } return absint( min( NumberUtil::round( ( $this->file_position / $size ) * 100 ), 100 ) ); } /** * Prepare a single product for create or update. * * @param array $data Item data. * @return KKART_Product|WP_Error */ protected function get_product_object( $data ) { $id = isset( $data['id'] ) ? absint( $data['id'] ) : 0; // Type is the most important part here because we need to be using the correct class and methods. if ( isset( $data['type'] ) ) { $types = array_keys( kkart_get_product_types() ); $types[] = 'variation'; if ( ! in_array( $data['type'], $types, true ) ) { return new WP_Error( 'kkart_product_importer_invalid_type', __( 'Invalid product type.', 'kkart' ), array( 'status' => 401 ) ); } try { // Prevent getting "variation_invalid_id" error message from Variation Data Store. if ( 'variation' === $data['type'] ) { $id = wp_update_post( array( 'ID' => $id, 'post_type' => 'product_variation', ) ); } $product = kkart_get_product_object( $data['type'], $id ); } catch ( KKART_Data_Exception $e ) { return new WP_Error( 'kkart_product_csv_importer_' . $e->getErrorCode(), $e->getMessage(), array( 'status' => 401 ) ); } } elseif ( ! empty( $data['id'] ) ) { $product = kkart_get_product( $id ); if ( ! $product ) { return new WP_Error( 'kkart_product_csv_importer_invalid_id', /* translators: %d: product ID */ sprintf( __( 'Invalid product ID %d.', 'kkart' ), $id ), array( 'id' => $id, 'status' => 401, ) ); } } else { $product = kkart_get_product_object( 'simple', $id ); } return apply_filters( 'kkart_product_import_get_product_object', $product, $data ); } /** * Process a single item and save. * * @throws Exception If item cannot be processed. * @param array $data Raw CSV data. * @return array|WP_Error */ protected function process_item( $data ) { try { do_action( 'kkart_product_import_before_process_item', $data ); $data = apply_filters( 'kkart_product_import_process_item_data', $data ); // Get product ID from SKU if created during the importation. if ( empty( $data['id'] ) && ! empty( $data['sku'] ) ) { $product_id = kkart_get_product_id_by_sku( $data['sku'] ); if ( $product_id ) { $data['id'] = $product_id; } } $object = $this->get_product_object( $data ); $updating = false; if ( is_wp_error( $object ) ) { return $object; } if ( $object->get_id() && 'importing' !== $object->get_status() ) { $updating = true; } if ( 'external' === $object->get_type() ) { unset( $data['manage_stock'], $data['stock_status'], $data['backorders'], $data['low_stock_amount'] ); } if ( 'variation' === $object->get_type() ) { if ( isset( $data['status'] ) && -1 === $data['status'] ) { $data['status'] = 0; // Variations cannot be drafts - set to private. } } if ( 'importing' === $object->get_status() ) { $object->set_status( 'publish' ); $object->set_slug( '' ); } $result = $object->set_props( array_diff_key( $data, array_flip( array( 'meta_data', 'raw_image_id', 'raw_gallery_image_ids', 'raw_attributes' ) ) ) ); if ( is_wp_error( $result ) ) { throw new Exception( $result->get_error_message() ); } if ( 'variation' === $object->get_type() ) { $this->set_variation_data( $object, $data ); } else { $this->set_product_data( $object, $data ); } $this->set_image_data( $object, $data ); $this->set_meta_data( $object, $data ); $object = apply_filters( 'kkart_product_import_pre_insert_product_object', $object, $data ); $object->save(); do_action( 'kkart_product_import_inserted_product_object', $object, $data ); return array( 'id' => $object->get_id(), 'updated' => $updating, ); } catch ( Exception $e ) { return new WP_Error( 'kkart_product_importer_error', $e->getMessage(), array( 'status' => $e->getCode() ) ); } } /** * Convert raw image URLs to IDs and set. * * @param KKART_Product $product Product instance. * @param array $data Item data. */ protected function set_image_data( &$product, $data ) { // Image URLs need converting to IDs before inserting. if ( isset( $data['raw_image_id'] ) ) { $product->set_image_id( $this->get_attachment_id_from_url( $data['raw_image_id'], $product->get_id() ) ); } // Gallery image URLs need converting to IDs before inserting. if ( isset( $data['raw_gallery_image_ids'] ) ) { $gallery_image_ids = array(); foreach ( $data['raw_gallery_image_ids'] as $image_id ) { $gallery_image_ids[] = $this->get_attachment_id_from_url( $image_id, $product->get_id() ); } $product->set_gallery_image_ids( $gallery_image_ids ); } } /** * Append meta data. * * @param KKART_Product $product Product instance. * @param array $data Item data. */ protected function set_meta_data( &$product, $data ) { if ( isset( $data['meta_data'] ) ) { foreach ( $data['meta_data'] as $meta ) { $product->update_meta_data( $meta['key'], $meta['value'] ); } } } /** * Set product data. * * @param KKART_Product $product Product instance. * @param array $data Item data. * @throws Exception If data cannot be set. */ protected function set_product_data( &$product, $data ) { if ( isset( $data['raw_attributes'] ) ) { $attributes = array(); $default_attributes = array(); $existing_attributes = $product->get_attributes(); foreach ( $data['raw_attributes'] as $position => $attribute ) { $attribute_id = 0; // Get ID if is a global attribute. if ( ! empty( $attribute['taxonomy'] ) ) { $attribute_id = $this->get_attribute_taxonomy_id( $attribute['name'] ); } // Set attribute visibility. if ( isset( $attribute['visible'] ) ) { $is_visible = $attribute['visible']; } else { $is_visible = 1; } // Get name. $attribute_name = $attribute_id ? kkart_attribute_taxonomy_name_by_id( $attribute_id ) : $attribute['name']; // Set if is a variation attribute based on existing attributes if possible so updates via CSV do not change this. $is_variation = 0; if ( $existing_attributes ) { foreach ( $existing_attributes as $existing_attribute ) { if ( $existing_attribute->get_name() === $attribute_name ) { $is_variation = $existing_attribute->get_variation(); break; } } } if ( $attribute_id ) { if ( isset( $attribute['value'] ) ) { $options = array_map( 'kkart_sanitize_term_text_based', $attribute['value'] ); $options = array_filter( $options, 'strlen' ); } else { $options = array(); } // Check for default attributes and set "is_variation". if ( ! empty( $attribute['default'] ) && in_array( $attribute['default'], $options, true ) ) { $default_term = get_term_by( 'name', $attribute['default'], $attribute_name ); if ( $default_term && ! is_wp_error( $default_term ) ) { $default = $default_term->slug; } else { $default = sanitize_title( $attribute['default'] ); } $default_attributes[ $attribute_name ] = $default; $is_variation = 1; } if ( ! empty( $options ) ) { $attribute_object = new KKART_Product_Attribute(); $attribute_object->set_id( $attribute_id ); $attribute_object->set_name( $attribute_name ); $attribute_object->set_options( $options ); $attribute_object->set_position( $position ); $attribute_object->set_visible( $is_visible ); $attribute_object->set_variation( $is_variation ); $attributes[] = $attribute_object; } } elseif ( isset( $attribute['value'] ) ) { // Check for default attributes and set "is_variation". if ( ! empty( $attribute['default'] ) && in_array( $attribute['default'], $attribute['value'], true ) ) { $default_attributes[ sanitize_title( $attribute['name'] ) ] = $attribute['default']; $is_variation = 1; } $attribute_object = new KKART_Product_Attribute(); $attribute_object->set_name( $attribute['name'] ); $attribute_object->set_options( $attribute['value'] ); $attribute_object->set_position( $position ); $attribute_object->set_visible( $is_visible ); $attribute_object->set_variation( $is_variation ); $attributes[] = $attribute_object; } } $product->set_attributes( $attributes ); // Set variable default attributes. if ( $product->is_type( 'variable' ) ) { $product->set_default_attributes( $default_attributes ); } } } /** * Set variation data. * * @param KKART_Product $variation Product instance. * @param array $data Item data. * @return KKART_Product|WP_Error * @throws Exception If data cannot be set. */ protected function set_variation_data( &$variation, $data ) { $parent = false; // Check if parent exist. if ( isset( $data['parent_id'] ) ) { $parent = kkart_get_product( $data['parent_id'] ); if ( $parent ) { $variation->set_parent_id( $parent->get_id() ); } } // Stop if parent does not exists. if ( ! $parent ) { return new WP_Error( 'kkart_product_importer_missing_variation_parent_id', __( 'Variation cannot be imported: Missing parent ID or parent does not exist yet.', 'kkart' ), array( 'status' => 401 ) ); } // Stop if parent is a product variation. if ( $parent->is_type( 'variation' ) ) { return new WP_Error( 'kkart_product_importer_parent_set_as_variation', __( 'Variation cannot be imported: Parent product cannot be a product variation', 'kkart' ), array( 'status' => 401 ) ); } if ( isset( $data['raw_attributes'] ) ) { $attributes = array(); $parent_attributes = $this->get_variation_parent_attributes( $data['raw_attributes'], $parent ); foreach ( $data['raw_attributes'] as $attribute ) { $attribute_id = 0; // Get ID if is a global attribute. if ( ! empty( $attribute['taxonomy'] ) ) { $attribute_id = $this->get_attribute_taxonomy_id( $attribute['name'] ); } if ( $attribute_id ) { $attribute_name = kkart_attribute_taxonomy_name_by_id( $attribute_id ); } else { $attribute_name = sanitize_title( $attribute['name'] ); } if ( ! isset( $parent_attributes[ $attribute_name ] ) || ! $parent_attributes[ $attribute_name ]->get_variation() ) { continue; } $attribute_key = sanitize_title( $parent_attributes[ $attribute_name ]->get_name() ); $attribute_value = isset( $attribute['value'] ) ? current( $attribute['value'] ) : ''; if ( $parent_attributes[ $attribute_name ]->is_taxonomy() ) { // If dealing with a taxonomy, we need to get the slug from the name posted to the API. $term = get_term_by( 'name', $attribute_value, $attribute_name ); if ( $term && ! is_wp_error( $term ) ) { $attribute_value = $term->slug; } else { $attribute_value = sanitize_title( $attribute_value ); } } $attributes[ $attribute_key ] = $attribute_value; } $variation->set_attributes( $attributes ); } } /** * Get variation parent attributes and set "is_variation". * * @param array $attributes Attributes list. * @param KKART_Product $parent Parent product data. * @return array */ protected function get_variation_parent_attributes( $attributes, $parent ) { $parent_attributes = $parent->get_attributes(); $require_save = false; foreach ( $attributes as $attribute ) { $attribute_id = 0; // Get ID if is a global attribute. if ( ! empty( $attribute['taxonomy'] ) ) { $attribute_id = $this->get_attribute_taxonomy_id( $attribute['name'] ); } if ( $attribute_id ) { $attribute_name = kkart_attribute_taxonomy_name_by_id( $attribute_id ); } else { $attribute_name = sanitize_title( $attribute['name'] ); } // Check if attribute handle variations. if ( isset( $parent_attributes[ $attribute_name ] ) && ! $parent_attributes[ $attribute_name ]->get_variation() ) { // Re-create the attribute to CRUD save and generate again. $parent_attributes[ $attribute_name ] = clone $parent_attributes[ $attribute_name ]; $parent_attributes[ $attribute_name ]->set_variation( 1 ); $require_save = true; } } // Save variation attributes. if ( $require_save ) { $parent->set_attributes( array_values( $parent_attributes ) ); $parent->save(); } return $parent_attributes; } /** * Get attachment ID. * * @param string $url Attachment URL. * @param int $product_id Product ID. * @return int * @throws Exception If attachment cannot be loaded. */ public function get_attachment_id_from_url( $url, $product_id ) { if ( empty( $url ) ) { return 0; } $id = 0; $upload_dir = wp_upload_dir( null, false ); $base_url = $upload_dir['baseurl'] . '/'; // Check first if attachment is inside the WordPress uploads directory, or we're given a filename only. if ( false !== strpos( $url, $base_url ) || false === strpos( $url, '://' ) ) { // Search for yyyy/mm/slug.extension or slug.extension - remove the base URL. $file = str_replace( $base_url, '', $url ); $args = array( 'post_type' => 'attachment', 'post_status' => 'any', 'fields' => 'ids', 'meta_query' => array( // @codingStandardsIgnoreLine. 'relation' => 'OR', array( 'key' => '_wp_attached_file', 'value' => '^' . $file, 'compare' => 'REGEXP', ), array( 'key' => '_wp_attached_file', 'value' => '/' . $file, 'compare' => 'LIKE', ), array( 'key' => '_kkart_attachment_source', 'value' => '/' . $file, 'compare' => 'LIKE', ), ), ); } else { // This is an external URL, so compare to source. $args = array( 'post_type' => 'attachment', 'post_status' => 'any', 'fields' => 'ids', 'meta_query' => array( // @codingStandardsIgnoreLine. array( 'value' => $url, 'key' => '_kkart_attachment_source', ), ), ); } $ids = get_posts( $args ); // @codingStandardsIgnoreLine. if ( $ids ) { $id = current( $ids ); } // Upload if attachment does not exists. if ( ! $id && stristr( $url, '://' ) ) { $upload = kkart_rest_upload_image_from_url( $url ); if ( is_wp_error( $upload ) ) { throw new Exception( $upload->get_error_message(), 400 ); } $id = kkart_rest_set_uploaded_image_as_attachment( $upload, $product_id ); if ( ! wp_attachment_is_image( $id ) ) { /* translators: %s: image URL */ throw new Exception( sprintf( __( 'Not able to attach "%s".', 'kkart' ), $url ), 400 ); } // Save attachment source for future reference. update_post_meta( $id, '_kkart_attachment_source', $url ); } if ( ! $id ) { /* translators: %s: image URL */ throw new Exception( sprintf( __( 'Unable to use image "%s".', 'kkart' ), $url ), 400 ); } return $id; } /** * Get attribute taxonomy ID from the imported data. * If does not exists register a new attribute. * * @param string $raw_name Attribute name. * @return int * @throws Exception If taxonomy cannot be loaded. */ public function get_attribute_taxonomy_id( $raw_name ) { global $wpdb, $kkart_product_attributes; // These are exported as labels, so convert the label to a name if possible first. $attribute_labels = wp_list_pluck( kkart_get_attribute_taxonomies(), 'attribute_label', 'attribute_name' ); $attribute_name = array_search( $raw_name, $attribute_labels, true ); if ( ! $attribute_name ) { $attribute_name = kkart_sanitize_taxonomy_name( $raw_name ); } $attribute_id = kkart_attribute_taxonomy_id_by_name( $attribute_name ); // Get the ID from the name. if ( $attribute_id ) { return $attribute_id; } // If the attribute does not exist, create it. $attribute_id = kkart_create_attribute( array( 'name' => $raw_name, 'slug' => $attribute_name, 'type' => 'select', 'order_by' => 'menu_order', 'has_archives' => false, ) ); if ( is_wp_error( $attribute_id ) ) { throw new Exception( $attribute_id->get_error_message(), 400 ); } // Register as taxonomy while importing. $taxonomy_name = kkart_attribute_taxonomy_name( $attribute_name ); register_taxonomy( $taxonomy_name, apply_filters( 'kkart_taxonomy_objects_' . $taxonomy_name, array( 'product' ) ), apply_filters( 'kkart_taxonomy_args_' . $taxonomy_name, array( 'labels' => array( 'name' => $raw_name, ), 'hierarchical' => true, 'show_ui' => false, 'query_var' => true, 'rewrite' => false, ) ) ); // Set product attributes global. $kkart_product_attributes = array(); foreach ( kkart_get_attribute_taxonomies() as $taxonomy ) { $kkart_product_attributes[ kkart_attribute_taxonomy_name( $taxonomy->attribute_name ) ] = $taxonomy; } return $attribute_id; } /** * Memory exceeded * * Ensures the batch process never exceeds 90% * of the maximum WordPress memory. * * @return bool */ protected function memory_exceeded() { $memory_limit = $this->get_memory_limit() * 0.9; // 90% of max memory $current_memory = memory_get_usage( true ); $return = false; if ( $current_memory >= $memory_limit ) { $return = true; } return apply_filters( 'kkart_product_importer_memory_exceeded', $return ); } /** * Get memory limit * * @return int */ protected function get_memory_limit() { if ( function_exists( 'ini_get' ) ) { $memory_limit = ini_get( 'memory_limit' ); } else { // Sensible default. $memory_limit = '128M'; } if ( ! $memory_limit || -1 === intval( $memory_limit ) ) { // Unlimited, set to 32GB. $memory_limit = '32000M'; } return intval( $memory_limit ) * 1024 * 1024; } /** * Time exceeded. * * Ensures the batch never exceeds a sensible time limit. * A timeout limit of 30s is common on shared hosting. * * @return bool */ protected function time_exceeded() { $finish = $this->start_time + apply_filters( 'kkart_product_importer_default_time_limit', 20 ); // 20 seconds $return = false; if ( time() >= $finish ) { $return = true; } return apply_filters( 'kkart_product_importer_time_exceeded', $return ); } /** * Explode CSV cell values using commas by default, and handling escaped * separators. * * @since 3.2.0 * @param string $value Value to explode. * @param string $separator Separator separating each value. Defaults to comma. * @return array */ protected function explode_values( $value, $separator = ',' ) { $value = str_replace( '\\,', '::separator::', $value ); $values = explode( $separator, $value ); $values = array_map( array( $this, 'explode_values_formatter' ), $values ); return $values; } /** * Remove formatting and trim each value. * * @since 3.2.0 * @param string $value Value to format. * @return string */ protected function explode_values_formatter( $value ) { return trim( str_replace( '::separator::', ',', $value ) ); } /** * The exporter prepends a ' to escape fields that start with =, +, - or @. * Remove the prepended ' character preceding those characters. * * @since 3.5.2 * @param string $value A string that may or may not have been escaped with '. * @return string */ protected function unescape_data( $value ) { $active_content_triggers = array( "'=", "'+", "'-", "'@" ); if ( in_array( mb_substr( $value, 0, 2 ), $active_content_triggers, true ) ) { $value = mb_substr( $value, 1 ); } return $value; } } PK!ZIA11kkart-stock-functions.phpnu[managing_stock() ) { // Some products (variations) can have their stock managed by their parent. Get the correct object to be updated here. $product_id_with_stock = $product->get_stock_managed_by_id(); $product_with_stock = $product_id_with_stock !== $product->get_id() ? kkart_get_product( $product_id_with_stock ) : $product; $data_store = KKART_Data_Store::load( 'product' ); // Update the database. $new_stock = $data_store->update_product_stock( $product_id_with_stock, $stock_quantity, $operation ); // Update the product object. $data_store->read_stock_quantity( $product_with_stock, $new_stock ); // If this is not being called during an update routine, save the product so stock status etc is in sync, and caches are cleared. if ( ! $updating ) { $product_with_stock->save(); } // Fire actions to let 3rd parties know the stock changed. if ( $product_with_stock->is_type( 'variation' ) ) { do_action( 'kkart_variation_set_stock', $product_with_stock ); } else { do_action( 'kkart_product_set_stock', $product_with_stock ); } return $product_with_stock->get_stock_quantity(); } return $product->get_stock_quantity(); } /** * Update a product's stock status. * * @param int $product_id Product ID. * @param string $status Status. */ function kkart_update_product_stock_status( $product_id, $status ) { $product = kkart_get_product( $product_id ); if ( $product ) { $product->set_stock_status( $status ); $product->save(); } } /** * When a payment is complete, we can reduce stock levels for items within an order. * * @since 3.0.0 * @param int $order_id Order ID. */ function kkart_maybe_reduce_stock_levels( $order_id ) { $order = kkart_get_order( $order_id ); if ( ! $order ) { return; } $stock_reduced = $order->get_data_store()->get_stock_reduced( $order_id ); $trigger_reduce = apply_filters( 'kkart_payment_complete_reduce_order_stock', ! $stock_reduced, $order_id ); // Only continue if we're reducing stock. if ( ! $trigger_reduce ) { return; } kkart_reduce_stock_levels( $order ); // Ensure stock is marked as "reduced" in case payment complete or other stock actions are called. $order->get_data_store()->set_stock_reduced( $order_id, true ); } add_action( 'kkart_payment_complete', 'kkart_maybe_reduce_stock_levels' ); add_action( 'kkart_order_status_completed', 'kkart_maybe_reduce_stock_levels' ); add_action( 'kkart_order_status_processing', 'kkart_maybe_reduce_stock_levels' ); add_action( 'kkart_order_status_on-hold', 'kkart_maybe_reduce_stock_levels' ); /** * When a payment is cancelled, restore stock. * * @since 3.0.0 * @param int $order_id Order ID. */ function kkart_maybe_increase_stock_levels( $order_id ) { $order = kkart_get_order( $order_id ); if ( ! $order ) { return; } $stock_reduced = $order->get_data_store()->get_stock_reduced( $order_id ); $trigger_increase = (bool) $stock_reduced; // Only continue if we're increasing stock. if ( ! $trigger_increase ) { return; } kkart_increase_stock_levels( $order ); // Ensure stock is not marked as "reduced" anymore. $order->get_data_store()->set_stock_reduced( $order_id, false ); } add_action( 'kkart_order_status_cancelled', 'kkart_maybe_increase_stock_levels' ); add_action( 'kkart_order_status_pending', 'kkart_maybe_increase_stock_levels' ); /** * Reduce stock levels for items within an order, if stock has not already been reduced for the items. * * @since 3.0.0 * @param int|KKART_Order $order_id Order ID or order instance. */ function kkart_reduce_stock_levels( $order_id ) { if ( is_a( $order_id, 'KKART_Order' ) ) { $order = $order_id; $order_id = $order->get_id(); } else { $order = kkart_get_order( $order_id ); } // We need an order, and a store with stock management to continue. if ( ! $order || 'yes' !== get_option( 'kkart_manage_stock' ) || ! apply_filters( 'kkart_can_reduce_order_stock', true, $order ) ) { return; } $changes = array(); // Loop over all items. foreach ( $order->get_items() as $item ) { if ( ! $item->is_type( 'line_item' ) ) { continue; } // Only reduce stock once for each item. $product = $item->get_product(); $item_stock_reduced = $item->get_meta( '_reduced_stock', true ); if ( $item_stock_reduced || ! $product || ! $product->managing_stock() ) { continue; } /** * Filter order item quantity. * * @param int|float $quantity Quantity. * @param KKART_Order $order Order data. * @param KKART_Order_Item_Product $item Order item data. */ $qty = apply_filters( 'kkart_order_item_quantity', $item->get_quantity(), $order, $item ); $item_name = $product->get_formatted_name(); $new_stock = kkart_update_product_stock( $product, $qty, 'decrease' ); if ( is_wp_error( $new_stock ) ) { /* translators: %s item name. */ $order->add_order_note( sprintf( __( 'Unable to reduce stock for item %s.', 'kkart' ), $item_name ) ); continue; } $item->add_meta_data( '_reduced_stock', $qty, true ); $item->save(); $changes[] = array( 'product' => $product, 'from' => $new_stock + $qty, 'to' => $new_stock, ); } kkart_trigger_stock_change_notifications( $order, $changes ); do_action( 'kkart_reduce_order_stock', $order ); } /** * After stock change events, triggers emails and adds order notes. * * @since 3.5.0 * @param KKART_Order $order order object. * @param array $changes Array of changes. */ function kkart_trigger_stock_change_notifications( $order, $changes ) { if ( empty( $changes ) ) { return; } $order_notes = array(); $no_stock_amount = absint( get_option( 'kkart_notify_no_stock_amount', 0 ) ); foreach ( $changes as $change ) { $order_notes[] = $change['product']->get_formatted_name() . ' ' . $change['from'] . '→' . $change['to']; $low_stock_amount = absint( kkart_get_low_stock_amount( kkart_get_product( $change['product']->get_id() ) ) ); if ( $change['to'] <= $no_stock_amount ) { do_action( 'kkart_no_stock', kkart_get_product( $change['product']->get_id() ) ); } elseif ( $change['to'] <= $low_stock_amount ) { do_action( 'kkart_low_stock', kkart_get_product( $change['product']->get_id() ) ); } if ( $change['to'] < 0 ) { do_action( 'kkart_product_on_backorder', array( 'product' => kkart_get_product( $change['product']->get_id() ), 'order_id' => $order->get_id(), 'quantity' => abs( $change['from'] - $change['to'] ), ) ); } } $order->add_order_note( __( 'Stock levels reduced:', 'kkart' ) . ' ' . implode( ', ', $order_notes ) ); } /** * Increase stock levels for items within an order. * * @since 3.0.0 * @param int|KKART_Order $order_id Order ID or order instance. */ function kkart_increase_stock_levels( $order_id ) { if ( is_a( $order_id, 'KKART_Order' ) ) { $order = $order_id; $order_id = $order->get_id(); } else { $order = kkart_get_order( $order_id ); } // We need an order, and a store with stock management to continue. if ( ! $order || 'yes' !== get_option( 'kkart_manage_stock' ) || ! apply_filters( 'kkart_can_restore_order_stock', true, $order ) ) { return; } $changes = array(); // Loop over all items. foreach ( $order->get_items() as $item ) { if ( ! $item->is_type( 'line_item' ) ) { continue; } // Only increase stock once for each item. $product = $item->get_product(); $item_stock_reduced = $item->get_meta( '_reduced_stock', true ); if ( ! $item_stock_reduced || ! $product || ! $product->managing_stock() ) { continue; } $item_name = $product->get_formatted_name(); $new_stock = kkart_update_product_stock( $product, $item_stock_reduced, 'increase' ); if ( is_wp_error( $new_stock ) ) { /* translators: %s item name. */ $order->add_order_note( sprintf( __( 'Unable to restore stock for item %s.', 'kkart' ), $item_name ) ); continue; } $item->delete_meta_data( '_reduced_stock' ); $item->save(); $changes[] = $item_name . ' ' . ( $new_stock - $item_stock_reduced ) . '→' . $new_stock; } if ( $changes ) { $order->add_order_note( __( 'Stock levels increased:', 'kkart' ) . ' ' . implode( ', ', $changes ) ); } do_action( 'kkart_restore_order_stock', $order ); } /** * See how much stock is being held in pending orders. * * @since 3.5.0 * @param KKART_Product $product Product to check. * @param integer $exclude_order_id Order ID to exclude. * @return int */ function kkart_get_held_stock_quantity( KKART_Product $product, $exclude_order_id = 0 ) { /** * Filter: kkart_hold_stock_for_checkout * Allows enable/disable hold stock functionality on checkout. * * @since 4.3.0 * @param bool $enabled Default to true if managing stock globally. */ if ( ! apply_filters( 'kkart_hold_stock_for_checkout', kkart_string_to_bool( get_option( 'kkart_manage_stock', 'yes' ) ) ) ) { return 0; } return ( new \Automattic\Kkart\Checkout\Helpers\ReserveStock() )->get_reserved_stock( $product, $exclude_order_id ); } /** * Hold stock for an order. * * @throws ReserveStockException If reserve stock fails. * * @since 4.1.0 * @param \KKART_Order|int $order Order ID or instance. */ function kkart_reserve_stock_for_order( $order ) { /** * Filter: kkart_hold_stock_for_checkout * Allows enable/disable hold stock functionality on checkout. * * @since @since 4.1.0 * @param bool $enabled Default to true if managing stock globally. */ if ( ! apply_filters( 'kkart_hold_stock_for_checkout', kkart_string_to_bool( get_option( 'kkart_manage_stock', 'yes' ) ) ) ) { return; } $order = $order instanceof KKART_Order ? $order : kkart_get_order( $order ); if ( $order ) { ( new \Automattic\Kkart\Checkout\Helpers\ReserveStock() )->reserve_stock_for_order( $order ); } } add_action( 'kkart_checkout_order_created', 'kkart_reserve_stock_for_order' ); /** * Release held stock for an order. * * @since 4.3.0 * @param \KKART_Order|int $order Order ID or instance. */ function kkart_release_stock_for_order( $order ) { /** * Filter: kkart_hold_stock_for_checkout * Allows enable/disable hold stock functionality on checkout. * * @since 4.3.0 * @param bool $enabled Default to true if managing stock globally. */ if ( ! apply_filters( 'kkart_hold_stock_for_checkout', kkart_string_to_bool( get_option( 'kkart_manage_stock', 'yes' ) ) ) ) { return; } $order = $order instanceof KKART_Order ? $order : kkart_get_order( $order ); if ( $order ) { ( new \Automattic\Kkart\Checkout\Helpers\ReserveStock() )->release_stock_for_order( $order ); } } add_action( 'kkart_checkout_order_exception', 'kkart_release_stock_for_order' ); add_action( 'kkart_payment_complete', 'kkart_release_stock_for_order', 11 ); add_action( 'kkart_order_status_cancelled', 'kkart_release_stock_for_order', 11 ); add_action( 'kkart_order_status_completed', 'kkart_release_stock_for_order', 11 ); add_action( 'kkart_order_status_processing', 'kkart_release_stock_for_order', 11 ); add_action( 'kkart_order_status_on-hold', 'kkart_release_stock_for_order', 11 ); /** * Return low stock amount to determine if notification needs to be sent * * @param KKART_Product $product Product to get data from. * @since 3.5.0 * @return int */ function kkart_get_low_stock_amount( KKART_Product $product ) { if ( $product->is_type( 'variation' ) ) { $product = kkart_get_product( $product->get_parent_id() ); } $low_stock_amount = $product->get_low_stock_amount(); if ( '' === $low_stock_amount ) { $low_stock_amount = get_option( 'kkart_notify_low_stock_amount', 2 ); } return $low_stock_amount; } PK!;őN33class-kkart-comments.phpnu[comment_post_ID ) should keep them safe since only admin and. * shop managers can view orders anyway. * * The frontend view order pages get around this filter by using remove_filter('comments_clauses', array( 'KKART_Comments' ,'exclude_order_comments'), 10, 1 ); * * @param array $clauses A compacted array of comment query clauses. * @return array */ public static function exclude_order_comments( $clauses ) { $clauses['where'] .= ( $clauses['where'] ? ' AND ' : '' ) . " comment_type != 'order_note' "; return $clauses; } /** * Exclude order comments from feed. * * @deprecated 3.1 * @param mixed $join Deprecated. */ public static function exclude_order_comments_from_feed_join( $join ) { kkart_deprecated_function( 'KKART_Comments::exclude_order_comments_from_feed_join', '3.1' ); } /** * Exclude order comments from queries and RSS. * * @param string $where The WHERE clause of the query. * @return string */ public static function exclude_order_comments_from_feed_where( $where ) { return $where . ( $where ? ' AND ' : '' ) . " comment_type != 'order_note' "; } /** * Exclude webhook comments from queries and RSS. * * @since 2.2 * @param array $clauses A compacted array of comment query clauses. * @return array */ public static function exclude_webhook_comments( $clauses ) { $clauses['where'] .= ( $clauses['where'] ? ' AND ' : '' ) . " comment_type != 'webhook_delivery' "; return $clauses; } /** * Exclude webhooks comments from feed. * * @deprecated 3.1 * @param mixed $join Deprecated. */ public static function exclude_webhook_comments_from_feed_join( $join ) { kkart_deprecated_function( 'KKART_Comments::exclude_webhook_comments_from_feed_join', '3.1' ); } /** * Exclude webhook comments from queries and RSS. * * @since 2.1 * @param string $where The WHERE clause of the query. * @return string */ public static function exclude_webhook_comments_from_feed_where( $where ) { return $where . ( $where ? ' AND ' : '' ) . " comment_type != 'webhook_delivery' "; } /** * Validate the comment ratings. * * @param array $comment_data Comment data. * @return array */ public static function check_comment_rating( $comment_data ) { // If posting a comment (not trackback etc) and not logged in. if ( ! is_admin() && isset( $_POST['comment_post_ID'], $_POST['rating'], $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) && empty( $_POST['rating'] ) && self::is_default_comment_type( $comment_data['comment_type'] ) && kkart_review_ratings_enabled() && kkart_review_ratings_required() ) { // WPCS: input var ok, CSRF ok. wp_die( esc_html__( 'Please rate the product.', 'kkart' ) ); exit; } return $comment_data; } /** * Rating field for comments. * * @param int $comment_id Comment ID. */ public static function add_comment_rating( $comment_id ) { if ( isset( $_POST['rating'], $_POST['comment_post_ID'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) ) { // WPCS: input var ok, CSRF ok. if ( ! $_POST['rating'] || $_POST['rating'] > 5 || $_POST['rating'] < 0 ) { // WPCS: input var ok, CSRF ok, sanitization ok. return; } add_comment_meta( $comment_id, 'rating', intval( $_POST['rating'] ), true ); // WPCS: input var ok, CSRF ok. $post_id = isset( $_POST['comment_post_ID'] ) ? absint( $_POST['comment_post_ID'] ) : 0; // WPCS: input var ok, CSRF ok. if ( $post_id ) { self::clear_transients( $post_id ); } } } /** * Modify recipient of review email. * * @param array $emails Emails. * @param int $comment_id Comment ID. * @return array */ public static function comment_moderation_recipients( $emails, $comment_id ) { $comment = get_comment( $comment_id ); if ( $comment && 'product' === get_post_type( $comment->comment_post_ID ) ) { $emails = array( get_option( 'admin_email' ) ); } return $emails; } /** * Ensure product average rating and review count is kept up to date. * * @param int $post_id Post ID. */ public static function clear_transients( $post_id ) { if ( 'product' === get_post_type( $post_id ) ) { $product = kkart_get_product( $post_id ); $product->set_rating_counts( self::get_rating_counts_for_product( $product ) ); $product->set_average_rating( self::get_average_rating_for_product( $product ) ); $product->set_review_count( self::get_review_count_for_product( $product ) ); $product->save(); } } /** * Delete comments count cache whenever there is * new comment or the status of a comment changes. Cache * will be regenerated next time KKART_Comments::wp_count_comments() * is called. */ public static function delete_comments_count_cache() { delete_transient( 'kkart_count_comments' ); } /** * Remove order notes and webhook delivery logs from wp_count_comments(). * * @since 2.2 * @param object $stats Comment stats. * @param int $post_id Post ID. * @return object */ public static function wp_count_comments( $stats, $post_id ) { global $wpdb; if ( 0 === $post_id ) { $stats = get_transient( 'kkart_count_comments' ); if ( ! $stats ) { $stats = array( 'total_comments' => 0, 'all' => 0, ); $count = $wpdb->get_results( " SELECT comment_approved, COUNT(*) AS num_comments FROM {$wpdb->comments} WHERE comment_type NOT IN ('action_log', 'order_note', 'webhook_delivery') GROUP BY comment_approved ", ARRAY_A ); $approved = array( '0' => 'moderated', '1' => 'approved', 'spam' => 'spam', 'trash' => 'trash', 'post-trashed' => 'post-trashed', ); foreach ( (array) $count as $row ) { // Don't count post-trashed toward totals. if ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash', 'spam' ), true ) ) { $stats['all'] += $row['num_comments']; $stats['total_comments'] += $row['num_comments']; } elseif ( ! in_array( $row['comment_approved'], array( 'post-trashed', 'trash' ), true ) ) { $stats['total_comments'] += $row['num_comments']; } if ( isset( $approved[ $row['comment_approved'] ] ) ) { $stats[ $approved[ $row['comment_approved'] ] ] = $row['num_comments']; } } foreach ( $approved as $key ) { if ( empty( $stats[ $key ] ) ) { $stats[ $key ] = 0; } } $stats = (object) $stats; set_transient( 'kkart_count_comments', $stats ); } } return $stats; } /** * Make sure WP displays avatars for comments with the `review` type. * * @since 2.3 * @param array $comment_types Comment types. * @return array */ public static function add_avatar_for_review_comment_type( $comment_types ) { return array_merge( $comment_types, array( 'review' ) ); } /** * Determine if a review is from a verified owner at submission. * * @param int $comment_id Comment ID. * @return bool */ public static function add_comment_purchase_verification( $comment_id ) { $comment = get_comment( $comment_id ); $verified = false; if ( 'product' === get_post_type( $comment->comment_post_ID ) ) { $verified = kkart_customer_bought_product( $comment->comment_author_email, $comment->user_id, $comment->comment_post_ID ); add_comment_meta( $comment_id, 'verified', (int) $verified, true ); } return $verified; } /** * Get product rating for a product. Please note this is not cached. * * @since 3.0.0 * @param KKART_Product $product Product instance. * @return float */ public static function get_average_rating_for_product( &$product ) { global $wpdb; $count = $product->get_rating_count(); if ( $count ) { $ratings = $wpdb->get_var( $wpdb->prepare( " SELECT SUM(meta_value) FROM $wpdb->commentmeta LEFT JOIN $wpdb->comments ON $wpdb->commentmeta.comment_id = $wpdb->comments.comment_ID WHERE meta_key = 'rating' AND comment_post_ID = %d AND comment_approved = '1' AND meta_value > 0 ", $product->get_id() ) ); $average = number_format( $ratings / $count, 2, '.', '' ); } else { $average = 0; } return $average; } /** * Get product review count for a product (not replies). Please note this is not cached. * * @since 3.0.0 * @param KKART_Product $product Product instance. * @return int */ public static function get_review_count_for_product( &$product ) { global $wpdb; $count = $wpdb->get_var( $wpdb->prepare( " SELECT COUNT(*) FROM $wpdb->comments WHERE comment_parent = 0 AND comment_post_ID = %d AND comment_approved = '1' AND comment_type = 'review' ", $product->get_id() ) ); return $count; } /** * Get product rating count for a product. Please note this is not cached. * * @since 3.0.0 * @param KKART_Product $product Product instance. * @return int[] */ public static function get_rating_counts_for_product( &$product ) { global $wpdb; $counts = array(); $raw_counts = $wpdb->get_results( $wpdb->prepare( " SELECT meta_value, COUNT( * ) as meta_value_count FROM $wpdb->commentmeta LEFT JOIN $wpdb->comments ON $wpdb->commentmeta.comment_id = $wpdb->comments.comment_ID WHERE meta_key = 'rating' AND comment_post_ID = %d AND comment_approved = '1' AND meta_value > 0 GROUP BY meta_value ", $product->get_id() ) ); foreach ( $raw_counts as $count ) { $counts[ $count->meta_value ] = absint( $count->meta_value_count ); // WPCS: slow query ok. } return $counts; } /** * Update comment type of product reviews. * * @since 3.5.0 * @param array $comment_data Comment data. * @return array */ public static function update_comment_type( $comment_data ) { if ( ! is_admin() && isset( $_POST['comment_post_ID'], $comment_data['comment_type'] ) && self::is_default_comment_type( $comment_data['comment_type'] ) && 'product' === get_post_type( absint( $_POST['comment_post_ID'] ) ) ) { // WPCS: input var ok, CSRF ok. $comment_data['comment_type'] = 'review'; } return $comment_data; } /** * Determines if a comment is of the default type. * * Prior to WordPress 5.5, '' was the default comment type. * As of 5.5, the default type is 'comment'. * * @since 4.3.0 * @param string $comment_type Comment type. * @return bool */ private static function is_default_comment_type( $comment_type ) { return ( '' === $comment_type || 'comment' === $comment_type ); } } KKART_Comments::init(); PK!X, , ]shipping/legacy-international-delivery/class-kkart-shipping-legacy-international-delivery.phpnu[id = 'legacy_international_delivery'; $this->method_title = __( 'International flat rate (legacy)', 'kkart' ); /* translators: %s: Admin shipping settings URL */ $this->method_description = '' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your Shipping zones.', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=shipping' ) ) . ''; $this->init(); add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Return the name of the option in the WP DB. * * @since 2.6.0 * @return string */ public function get_option_key() { return $this->plugin_id . 'international_delivery_settings'; } /** * Initialise settings form fields. */ public function init_form_fields() { parent::init_form_fields(); $this->form_fields['availability'] = array( 'title' => __( 'Availability', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'description' => '', 'default' => 'including', 'options' => array( 'including' => __( 'Selected countries', 'kkart' ), 'excluding' => __( 'Excluding selected countries', 'kkart' ), ), ); } /** * Check if package is available. * * @param array $package Package information. * @return bool */ public function is_available( $package ) { if ( 'no' === $this->enabled ) { return false; } if ( 'including' === $this->availability ) { if ( is_array( $this->countries ) && ! in_array( $package['destination']['country'], $this->countries, true ) ) { return false; } } else { if ( is_array( $this->countries ) && ( in_array( $package['destination']['country'], $this->countries, true ) || ! $package['destination']['country'] ) ) { return false; } } return apply_filters( 'kkart_shipping_' . $this->id . '_is_available', true, $package, $this ); } } PK!8:R!Kshipping/legacy-free-shipping/class-kkart-shipping-legacy-free-shipping.phpnu[id = 'legacy_free_shipping'; $this->method_title = __( 'Free shipping (legacy)', 'kkart' ); /* translators: %s: Admin shipping settings URL */ $this->method_description = '' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your Shipping zones.', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=shipping' ) ) . ''; $this->init(); } /** * Process and redirect if disabled. */ public function process_admin_options() { parent::process_admin_options(); if ( 'no' === $this->settings['enabled'] ) { wp_redirect( admin_url( 'admin.php?page=kkart-settings&tab=shipping§ion=options' ) ); exit; } } /** * Return the name of the option in the WP DB. * * @since 2.6.0 * @return string */ public function get_option_key() { return $this->plugin_id . 'free_shipping_settings'; } /** * Init function. */ public function init() { // Load the settings. $this->init_form_fields(); $this->init_settings(); // Define user set variables. $this->enabled = $this->get_option( 'enabled' ); $this->title = $this->get_option( 'title' ); $this->min_amount = $this->get_option( 'min_amount', 0 ); $this->availability = $this->get_option( 'availability' ); $this->countries = $this->get_option( 'countries' ); $this->requires = $this->get_option( 'requires' ); // Actions. add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Initialise Gateway Settings Form Fields. */ public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Once disabled, this legacy method will no longer be available.', 'kkart' ), 'default' => 'no', ), 'title' => array( 'title' => __( 'Method title', 'kkart' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => __( 'Free Shipping', 'kkart' ), 'desc_tip' => true, ), 'availability' => array( 'title' => __( 'Method availability', 'kkart' ), 'type' => 'select', 'default' => 'all', 'class' => 'availability kkart-enhanced-select', 'options' => array( 'all' => __( 'All allowed countries', 'kkart' ), 'specific' => __( 'Specific Countries', 'kkart' ), ), ), 'countries' => array( 'title' => __( 'Specific countries', 'kkart' ), 'type' => 'multiselect', 'class' => 'kkart-enhanced-select', 'css' => 'width: 400px;', 'default' => '', 'options' => KKART()->countries->get_shipping_countries(), 'custom_attributes' => array( 'data-placeholder' => __( 'Select some countries', 'kkart' ), ), ), 'requires' => array( 'title' => __( 'Free shipping requires...', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'default' => '', 'options' => array( '' => __( 'N/A', 'kkart' ), 'coupon' => __( 'A valid free shipping coupon', 'kkart' ), 'min_amount' => __( 'A minimum order amount', 'kkart' ), 'either' => __( 'A minimum order amount OR a coupon', 'kkart' ), 'both' => __( 'A minimum order amount AND a coupon', 'kkart' ), ), ), 'min_amount' => array( 'title' => __( 'Minimum order amount', 'kkart' ), 'type' => 'price', 'placeholder' => kkart_format_localized_price( 0 ), 'description' => __( 'Users will need to spend this amount to get free shipping (if enabled above).', 'kkart' ), 'default' => '0', 'desc_tip' => true, ), ); } /** * Check if package is available. * * @param array $package Package information. * @return bool */ public function is_available( $package ) { if ( 'no' === $this->enabled ) { return false; } if ( 'specific' === $this->availability ) { $ship_to_countries = $this->countries; } else { $ship_to_countries = array_keys( KKART()->countries->get_shipping_countries() ); } if ( is_array( $ship_to_countries ) && ! in_array( $package['destination']['country'], $ship_to_countries, true ) ) { return false; } // Enabled logic. $is_available = false; $has_coupon = false; $has_met_min_amount = false; if ( in_array( $this->requires, array( 'coupon', 'either', 'both' ), true ) ) { $coupons = KKART()->cart->get_coupons(); if ( $coupons ) { foreach ( $coupons as $code => $coupon ) { if ( $coupon->is_valid() && $coupon->get_free_shipping() ) { $has_coupon = true; } } } } if ( in_array( $this->requires, array( 'min_amount', 'either', 'both' ), true ) ) { $total = KKART()->cart->get_displayed_subtotal(); if ( KKART()->cart->display_prices_including_tax() ) { $total = NumberUtil::round( $total - ( KKART()->cart->get_discount_total() + KKART()->cart->get_discount_tax() ), kkart_get_price_decimals() ); } else { $total = NumberUtil::round( $total - KKART()->cart->get_discount_total(), kkart_get_price_decimals() ); } if ( $total >= $this->min_amount ) { $has_met_min_amount = true; } } switch ( $this->requires ) { case 'min_amount': if ( $has_met_min_amount ) { $is_available = true; } break; case 'coupon': if ( $has_coupon ) { $is_available = true; } break; case 'both': if ( $has_met_min_amount && $has_coupon ) { $is_available = true; } break; case 'either': if ( $has_met_min_amount || $has_coupon ) { $is_available = true; } break; default: $is_available = true; break; } return apply_filters( 'kkart_shipping_' . $this->id . '_is_available', $is_available, $package, $this ); } /** * Calculate shipping. * * @param array $package Package information. */ public function calculate_shipping( $package = array() ) { $args = array( 'id' => $this->id, 'label' => $this->title, 'cost' => 0, 'taxes' => false, 'package' => $package, ); $this->add_rate( $args ); } } PK!Y ;shipping/local-pickup/class-kkart-shipping-local-pickup.phpnu[id = 'local_pickup'; $this->instance_id = absint( $instance_id ); $this->method_title = __( 'Local pickup', 'kkart' ); $this->method_description = __( 'Allow customers to pick up orders themselves. By default, when using local pickup store base taxes will apply regardless of customer address.', 'kkart' ); $this->supports = array( 'shipping-zones', 'instance-settings', 'instance-settings-modal', ); $this->init(); } /** * Initialize local pickup. */ public function init() { // Load the settings. $this->init_form_fields(); $this->init_settings(); // Define user set variables. $this->title = $this->get_option( 'title' ); $this->tax_status = $this->get_option( 'tax_status' ); $this->cost = $this->get_option( 'cost' ); // Actions. add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Calculate local pickup shipping. * * @param array $package Package information. */ public function calculate_shipping( $package = array() ) { $this->add_rate( array( 'label' => $this->title, 'package' => $package, 'cost' => $this->cost, ) ); } /** * Init form fields. */ public function init_form_fields() { $this->instance_form_fields = array( 'title' => array( 'title' => __( 'Title', 'kkart' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => __( 'Local pickup', 'kkart' ), 'desc_tip' => true, ), 'tax_status' => array( 'title' => __( 'Tax status', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'default' => 'taxable', 'options' => array( 'taxable' => __( 'Taxable', 'kkart' ), 'none' => _x( 'None', 'Tax status', 'kkart' ), ), ), 'cost' => array( 'title' => __( 'Cost', 'kkart' ), 'type' => 'text', 'placeholder' => '0', 'description' => __( 'Optional cost for local pickup.', 'kkart' ), 'default' => '', 'desc_tip' => true, ), ); } } PK!T2djMshipping/legacy-local-delivery/class-kkart-shipping-legacy-local-delivery.phpnu[id = 'legacy_local_delivery'; $this->method_title = __( 'Local delivery (legacy)', 'kkart' ); /* translators: %s: Admin shipping settings URL */ $this->method_description = '' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your Shipping zones.', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=shipping' ) ) . ''; $this->init(); } /** * Process and redirect if disabled. */ public function process_admin_options() { parent::process_admin_options(); if ( 'no' === $this->settings['enabled'] ) { wp_redirect( admin_url( 'admin.php?page=kkart-settings&tab=shipping§ion=options' ) ); exit; } } /** * Return the name of the option in the WP DB. * * @since 2.6.0 * @return string */ public function get_option_key() { return $this->plugin_id . 'local_delivery_settings'; } /** * Init function. */ public function init() { // Load the settings. $this->init_form_fields(); $this->init_settings(); // Define user set variables. $this->title = $this->get_option( 'title' ); $this->type = $this->get_option( 'type' ); $this->fee = $this->get_option( 'fee' ); $this->type = $this->get_option( 'type' ); $this->codes = $this->get_option( 'codes' ); $this->availability = $this->get_option( 'availability' ); $this->countries = $this->get_option( 'countries' ); add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Calculate_shipping function. * * @param array $package (default: array()). */ public function calculate_shipping( $package = array() ) { $shipping_total = 0; switch ( $this->type ) { case 'fixed': $shipping_total = $this->fee; break; case 'percent': $shipping_total = $package['contents_cost'] * ( $this->fee / 100 ); break; case 'product': foreach ( $package['contents'] as $item_id => $values ) { if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) { $shipping_total += $this->fee * $values['quantity']; } } break; } $rate = array( 'id' => $this->id, 'label' => $this->title, 'cost' => $shipping_total, 'package' => $package, ); $this->add_rate( $rate ); } /** * Init form fields. */ public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Once disabled, this legacy method will no longer be available.', 'kkart' ), 'default' => 'no', ), 'title' => array( 'title' => __( 'Title', 'kkart' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => __( 'Local delivery', 'kkart' ), 'desc_tip' => true, ), 'type' => array( 'title' => __( 'Fee type', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'description' => __( 'How to calculate delivery charges', 'kkart' ), 'default' => 'fixed', 'options' => array( 'fixed' => __( 'Fixed amount', 'kkart' ), 'percent' => __( 'Percentage of cart total', 'kkart' ), 'product' => __( 'Fixed amount per product', 'kkart' ), ), 'desc_tip' => true, ), 'fee' => array( 'title' => __( 'Delivery fee', 'kkart' ), 'type' => 'price', 'description' => __( 'What fee do you want to charge for local delivery, disregarded if you choose free. Leave blank to disable.', 'kkart' ), 'default' => '', 'desc_tip' => true, 'placeholder' => kkart_format_localized_price( 0 ), ), 'codes' => array( 'title' => __( 'Allowed ZIP/post codes', 'kkart' ), 'type' => 'text', 'desc_tip' => __( 'What ZIP/post codes are available for local delivery?', 'kkart' ), 'default' => '', 'description' => __( 'Separate codes with a comma. Accepts wildcards, e.g. P* will match a postcode of PE30. Also accepts a pattern, e.g. NG1___ would match NG1 1AA but not NG10 1AA', 'kkart' ), 'placeholder' => 'e.g. 12345, 56789', ), 'availability' => array( 'title' => __( 'Method availability', 'kkart' ), 'type' => 'select', 'default' => 'all', 'class' => 'availability kkart-enhanced-select', 'options' => array( 'all' => __( 'All allowed countries', 'kkart' ), 'specific' => __( 'Specific Countries', 'kkart' ), ), ), 'countries' => array( 'title' => __( 'Specific countries', 'kkart' ), 'type' => 'multiselect', 'class' => 'kkart-enhanced-select', 'css' => 'width: 400px;', 'default' => '', 'options' => KKART()->countries->get_shipping_countries(), 'custom_attributes' => array( 'data-placeholder' => __( 'Select some countries', 'kkart' ), ), ), ); } } PK!T``=shipping/free-shipping/class-kkart-shipping-free-shipping.phpnu[id = 'free_shipping'; $this->instance_id = absint( $instance_id ); $this->method_title = __( 'Free shipping', 'kkart' ); $this->method_description = __( 'Free shipping is a special method which can be triggered with coupons and minimum spends.', 'kkart' ); $this->supports = array( 'shipping-zones', 'instance-settings', 'instance-settings-modal', ); $this->init(); } /** * Initialize free shipping. */ public function init() { // Load the settings. $this->init_form_fields(); $this->init_settings(); // Define user set variables. $this->title = $this->get_option( 'title' ); $this->min_amount = $this->get_option( 'min_amount', 0 ); $this->requires = $this->get_option( 'requires' ); $this->ignore_discounts = $this->get_option( 'ignore_discounts' ); // Actions. add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); add_action( 'admin_footer', array( 'KKART_Shipping_Free_Shipping', 'enqueue_admin_js' ), 10 ); // Priority needs to be higher than kkart_print_js (25). } /** * Init form fields. */ public function init_form_fields() { $this->instance_form_fields = array( 'title' => array( 'title' => __( 'Title', 'kkart' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => $this->method_title, 'desc_tip' => true, ), 'requires' => array( 'title' => __( 'Free shipping requires...', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'default' => '', 'options' => array( '' => __( 'N/A', 'kkart' ), 'coupon' => __( 'A valid free shipping coupon', 'kkart' ), 'min_amount' => __( 'A minimum order amount', 'kkart' ), 'either' => __( 'A minimum order amount OR a coupon', 'kkart' ), 'both' => __( 'A minimum order amount AND a coupon', 'kkart' ), ), ), 'min_amount' => array( 'title' => __( 'Minimum order amount', 'kkart' ), 'type' => 'price', 'placeholder' => kkart_format_localized_price( 0 ), 'description' => __( 'Users will need to spend this amount to get free shipping (if enabled above).', 'kkart' ), 'default' => '0', 'desc_tip' => true, ), 'ignore_discounts' => array( 'title' => __( 'Coupons discounts', 'kkart' ), 'label' => __( 'Apply minimum order rule before coupon discount', 'kkart' ), 'type' => 'checkbox', 'description' => __( 'If checked, free shipping would be available based on pre-discount order amount.', 'kkart' ), 'default' => 'no', 'desc_tip' => true, ), ); } /** * Get setting form fields for instances of this shipping method within zones. * * @return array */ public function get_instance_form_fields() { return parent::get_instance_form_fields(); } /** * See if free shipping is available based on the package and cart. * * @param array $package Shipping package. * @return bool */ public function is_available( $package ) { $has_coupon = false; $has_met_min_amount = false; if ( in_array( $this->requires, array( 'coupon', 'either', 'both' ), true ) ) { $coupons = KKART()->cart->get_coupons(); if ( $coupons ) { foreach ( $coupons as $code => $coupon ) { if ( $coupon->is_valid() && $coupon->get_free_shipping() ) { $has_coupon = true; break; } } } } if ( in_array( $this->requires, array( 'min_amount', 'either', 'both' ), true ) ) { $total = KKART()->cart->get_displayed_subtotal(); if ( KKART()->cart->display_prices_including_tax() ) { $total = $total - KKART()->cart->get_discount_tax(); } if ( 'no' === $this->ignore_discounts ) { $total = $total - KKART()->cart->get_discount_total(); } $total = NumberUtil::round( $total, kkart_get_price_decimals() ); if ( $total >= $this->min_amount ) { $has_met_min_amount = true; } } switch ( $this->requires ) { case 'min_amount': $is_available = $has_met_min_amount; break; case 'coupon': $is_available = $has_coupon; break; case 'both': $is_available = $has_met_min_amount && $has_coupon; break; case 'either': $is_available = $has_met_min_amount || $has_coupon; break; default: $is_available = true; break; } return apply_filters( 'kkart_shipping_' . $this->id . '_is_available', $is_available, $package, $this ); } /** * Called to calculate shipping rates for this method. Rates can be added using the add_rate() method. * * @uses KKART_Shipping_Method::add_rate() * * @param array $package Shipping package. */ public function calculate_shipping( $package = array() ) { $this->add_rate( array( 'label' => $this->title, 'cost' => 0, 'taxes' => false, 'package' => $package, ) ); } /** * Enqueue JS to handle free shipping options. * * Static so that's enqueued only once. */ public static function enqueue_admin_js() { kkart_enqueue_js( "jQuery( function( $ ) { function wcFreeShippingShowHideMinAmountField( el ) { var form = $( el ).closest( 'form' ); var minAmountField = $( '#kkart_free_shipping_min_amount', form ).closest( 'tr' ); var ignoreDiscountField = $( '#kkart_free_shipping_ignore_discounts', form ).closest( 'tr' ); if ( 'coupon' === $( el ).val() || '' === $( el ).val() ) { minAmountField.hide(); ignoreDiscountField.hide(); } else { minAmountField.show(); ignoreDiscountField.show(); } } $( document.body ).on( 'change', '#kkart_free_shipping_requires', function() { wcFreeShippingShowHideMinAmountField( this ); }); // Change while load. $( '#kkart_free_shipping_requires' ).change(); $( document.body ).on( 'kkart_backbone_modal_loaded', function( evt, target ) { if ( 'kkart-modal-shipping-method-settings' === target ) { wcFreeShippingShowHideMinAmountField( $( '#kkart-backbone-modal-dialog #kkart_free_shipping_requires', evt.currentTarget ) ); } } ); });" ); } } PK!4M4Ishipping/legacy-local-pickup/class-kkart-shipping-legacy-local-pickup.phpnu[id = 'legacy_local_pickup'; $this->method_title = __( 'Local pickup (legacy)', 'kkart' ); /* translators: %s: Admin shipping settings URL */ $this->method_description = '' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your Shipping zones.', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=shipping' ) ) . ''; $this->init(); } /** * Process and redirect if disabled. */ public function process_admin_options() { parent::process_admin_options(); if ( 'no' === $this->settings['enabled'] ) { wp_redirect( admin_url( 'admin.php?page=kkart-settings&tab=shipping§ion=options' ) ); exit; } } /** * Return the name of the option in the WP DB. * * @since 2.6.0 * @return string */ public function get_option_key() { return $this->plugin_id . 'local_pickup_settings'; } /** * Init function. */ public function init() { // Load the settings. $this->init_form_fields(); $this->init_settings(); // Define user set variables. $this->enabled = $this->get_option( 'enabled' ); $this->title = $this->get_option( 'title' ); $this->codes = $this->get_option( 'codes' ); $this->availability = $this->get_option( 'availability' ); $this->countries = $this->get_option( 'countries' ); // Actions. add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Calculate shipping. * * @param array $package Package information. */ public function calculate_shipping( $package = array() ) { $rate = array( 'id' => $this->id, 'label' => $this->title, 'package' => $package, ); $this->add_rate( $rate ); } /** * Initialize form fields. */ public function init_form_fields() { $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Once disabled, this legacy method will no longer be available.', 'kkart' ), 'default' => 'no', ), 'title' => array( 'title' => __( 'Title', 'kkart' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => __( 'Local pickup', 'kkart' ), 'desc_tip' => true, ), 'codes' => array( 'title' => __( 'Allowed ZIP/post codes', 'kkart' ), 'type' => 'text', 'desc_tip' => __( 'What ZIP/post codes are available for local pickup?', 'kkart' ), 'default' => '', 'description' => __( 'Separate codes with a comma. Accepts wildcards, e.g. P* will match a postcode of PE30. Also accepts a pattern, e.g. NG1___ would match NG1 1AA but not NG10 1AA', 'kkart' ), 'placeholder' => 'e.g. 12345, 56789', ), 'availability' => array( 'title' => __( 'Method availability', 'kkart' ), 'type' => 'select', 'default' => 'all', 'class' => 'availability kkart-enhanced-select', 'options' => array( 'all' => __( 'All allowed countries', 'kkart' ), 'specific' => __( 'Specific countries', 'kkart' ), ), ), 'countries' => array( 'title' => __( 'Specific countries', 'kkart' ), 'type' => 'multiselect', 'class' => 'kkart-enhanced-select', 'css' => 'width: 400px;', 'default' => '', 'options' => KKART()->countries->get_shipping_countries(), 'custom_attributes' => array( 'data-placeholder' => __( 'Select some countries', 'kkart' ), ), ), ); } /** * Get postcodes for this method. * * @return array */ public function get_valid_postcodes() { $codes = array(); if ( '' !== $this->codes ) { foreach ( explode( ',', $this->codes ) as $code ) { $codes[] = strtoupper( trim( $code ) ); } } return $codes; } /** * See if a given postcode matches valid postcodes. * * @param string $postcode Postcode to check. * @param string $country code Code of the country to check postcode against. * @return boolean */ public function is_valid_postcode( $postcode, $country ) { $codes = $this->get_valid_postcodes(); $postcode = $this->clean( $postcode ); $formatted_postcode = kkart_format_postcode( $postcode, $country ); if ( in_array( $postcode, $codes, true ) || in_array( $formatted_postcode, $codes, true ) ) { return true; } // Pattern matching. foreach ( $codes as $c ) { $pattern = '/^' . str_replace( '_', '[0-9a-zA-Z]', preg_quote( $c ) ) . '$/i'; if ( preg_match( $pattern, $postcode ) ) { return true; } } // Wildcard search. $wildcard_postcode = $formatted_postcode . '*'; $postcode_length = strlen( $formatted_postcode ); for ( $i = 0; $i < $postcode_length; $i++ ) { if ( in_array( $wildcard_postcode, $codes, true ) ) { return true; } $wildcard_postcode = substr( $wildcard_postcode, 0, -2 ) . '*'; } return false; } /** * See if the method is available. * * @param array $package Package information. * @return bool */ public function is_available( $package ) { $is_available = 'yes' === $this->enabled; if ( $is_available && $this->get_valid_postcodes() ) { $is_available = $this->is_valid_postcode( $package['destination']['postcode'], $package['destination']['country'] ); } if ( $is_available ) { if ( 'specific' === $this->availability ) { $ship_to_countries = $this->countries; } else { $ship_to_countries = array_keys( KKART()->countries->get_shipping_countries() ); } if ( is_array( $ship_to_countries ) && ! in_array( $package['destination']['country'], $ship_to_countries, true ) ) { $is_available = false; } } return apply_filters( 'kkart_shipping_' . $this->id . '_is_available', $is_available, $package, $this ); } /** * Clean function. * * @access public * @param mixed $code Code. * @return string */ public function clean( $code ) { return str_replace( '-', '', sanitize_title( $code ) ) . ( strstr( $code, '*' ) ? '*' : '' ); } } PK!0N 2shipping/flat-rate/includes/settings-flat-rate.phpnu[10.00 * [qty].', 'kkart' ) . '

' . __( 'Use [qty] for the number of items,
[cost] for the total cost of items, and [fee percent="10" min_fee="20" max_fee=""] for percentage based fees.', 'kkart' ); $settings = array( 'title' => array( 'title' => __( 'Method title', 'kkart' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => __( 'Flat rate', 'kkart' ), 'desc_tip' => true, ), 'tax_status' => array( 'title' => __( 'Tax status', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'default' => 'taxable', 'options' => array( 'taxable' => __( 'Taxable', 'kkart' ), 'none' => _x( 'None', 'Tax status', 'kkart' ), ), ), 'cost' => array( 'title' => __( 'Cost', 'kkart' ), 'type' => 'text', 'placeholder' => '', 'description' => $cost_desc, 'default' => '0', 'desc_tip' => true, 'sanitize_callback' => array( $this, 'sanitize_cost' ), ), ); $shipping_classes = KKART()->shipping()->get_shipping_classes(); if ( ! empty( $shipping_classes ) ) { $settings['class_costs'] = array( 'title' => __( 'Shipping class costs', 'kkart' ), 'type' => 'title', 'default' => '', /* translators: %s: URL for link. */ 'description' => sprintf( __( 'These costs can optionally be added based on the product shipping class.', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=shipping§ion=classes' ) ), ); foreach ( $shipping_classes as $shipping_class ) { if ( ! isset( $shipping_class->term_id ) ) { continue; } $settings[ 'class_cost_' . $shipping_class->term_id ] = array( /* translators: %s: shipping class name */ 'title' => sprintf( __( '"%s" shipping class cost', 'kkart' ), esc_html( $shipping_class->name ) ), 'type' => 'text', 'placeholder' => __( 'N/A', 'kkart' ), 'description' => $cost_desc, 'default' => $this->get_option( 'class_cost_' . $shipping_class->slug ), // Before 2.5.0, we used slug here which caused issues with long setting names. 'desc_tip' => true, 'sanitize_callback' => array( $this, 'sanitize_cost' ), ); } $settings['no_class_cost'] = array( 'title' => __( 'No shipping class cost', 'kkart' ), 'type' => 'text', 'placeholder' => __( 'N/A', 'kkart' ), 'description' => $cost_desc, 'default' => '', 'desc_tip' => true, 'sanitize_callback' => array( $this, 'sanitize_cost' ), ); $settings['type'] = array( 'title' => __( 'Calculation type', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'default' => 'class', 'options' => array( 'class' => __( 'Per class: Charge shipping for each shipping class individually', 'kkart' ), 'order' => __( 'Per order: Charge shipping for the most expensive shipping class', 'kkart' ), ), ); } return $settings; PK!05shipping/flat-rate/class-kkart-shipping-flat-rate.phpnu[id = 'flat_rate'; $this->instance_id = absint( $instance_id ); $this->method_title = __( 'Flat rate', 'kkart' ); $this->method_description = __( 'Lets you charge a fixed rate for shipping.', 'kkart' ); $this->supports = array( 'shipping-zones', 'instance-settings', 'instance-settings-modal', ); $this->init(); add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Init user set variables. */ public function init() { $this->instance_form_fields = include __DIR__ . '/includes/settings-flat-rate.php'; $this->title = $this->get_option( 'title' ); $this->tax_status = $this->get_option( 'tax_status' ); $this->cost = $this->get_option( 'cost' ); $this->type = $this->get_option( 'type', 'class' ); } /** * Evaluate a cost from a sum/string. * * @param string $sum Sum of shipping. * @param array $args Args, must contain `cost` and `qty` keys. Having `array()` as default is for back compat reasons. * @return string */ protected function evaluate_cost( $sum, $args = array() ) { // Add warning for subclasses. if ( ! is_array( $args ) || ! array_key_exists( 'qty', $args ) || ! array_key_exists( 'cost', $args ) ) { kkart_doing_it_wrong( __FUNCTION__, '$args must contain `cost` and `qty` keys.', '4.0.1' ); } include_once KKART()->plugin_path() . '/includes/libraries/class-kkart-eval-math.php'; // Allow 3rd parties to process shipping cost arguments. $args = apply_filters( 'kkart_evaluate_shipping_cost_args', $args, $sum, $this ); $locale = localeconv(); $decimals = array( kkart_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'], ',' ); $this->fee_cost = $args['cost']; // Expand shortcodes. add_shortcode( 'fee', array( $this, 'fee' ) ); $sum = do_shortcode( str_replace( array( '[qty]', '[cost]', ), array( $args['qty'], $args['cost'], ), $sum ) ); remove_shortcode( 'fee', array( $this, 'fee' ) ); // Remove whitespace from string. $sum = preg_replace( '/\s+/', '', $sum ); // Remove locale from string. $sum = str_replace( $decimals, '.', $sum ); // Trim invalid start/end characters. $sum = rtrim( ltrim( $sum, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" ); // Do the math. return $sum ? KKART_Eval_Math::evaluate( $sum ) : 0; } /** * Work out fee (shortcode). * * @param array $atts Attributes. * @return string */ public function fee( $atts ) { $atts = shortcode_atts( array( 'percent' => '', 'min_fee' => '', 'max_fee' => '', ), $atts, 'fee' ); $calculated_fee = 0; if ( $atts['percent'] ) { $calculated_fee = $this->fee_cost * ( floatval( $atts['percent'] ) / 100 ); } if ( $atts['min_fee'] && $calculated_fee < $atts['min_fee'] ) { $calculated_fee = $atts['min_fee']; } if ( $atts['max_fee'] && $calculated_fee > $atts['max_fee'] ) { $calculated_fee = $atts['max_fee']; } return $calculated_fee; } /** * Calculate the shipping costs. * * @param array $package Package of items from cart. */ public function calculate_shipping( $package = array() ) { $rate = array( 'id' => $this->get_rate_id(), 'label' => $this->title, 'cost' => 0, 'package' => $package, ); // Calculate the costs. $has_costs = false; // True when a cost is set. False if all costs are blank strings. $cost = $this->get_option( 'cost' ); if ( '' !== $cost ) { $has_costs = true; $rate['cost'] = $this->evaluate_cost( $cost, array( 'qty' => $this->get_package_item_qty( $package ), 'cost' => $package['contents_cost'], ) ); } // Add shipping class costs. $shipping_classes = KKART()->shipping()->get_shipping_classes(); if ( ! empty( $shipping_classes ) ) { $found_shipping_classes = $this->find_shipping_classes( $package ); $highest_class_cost = 0; foreach ( $found_shipping_classes as $shipping_class => $products ) { // Also handles BW compatibility when slugs were used instead of ids. $shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' ); $class_cost_string = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' ); if ( '' === $class_cost_string ) { continue; } $has_costs = true; $class_cost = $this->evaluate_cost( $class_cost_string, array( 'qty' => array_sum( wp_list_pluck( $products, 'quantity' ) ), 'cost' => array_sum( wp_list_pluck( $products, 'line_total' ) ), ) ); if ( 'class' === $this->type ) { $rate['cost'] += $class_cost; } else { $highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost; } } if ( 'order' === $this->type && $highest_class_cost ) { $rate['cost'] += $highest_class_cost; } } if ( $has_costs ) { $this->add_rate( $rate ); } /** * Developers can add additional flat rates based on this one via this action since @version 2.4. * * Previously there were (overly complex) options to add additional rates however this was not user. * friendly and goes against what Flat Rate Shipping was originally intended for. */ do_action( 'kkart_' . $this->id . '_shipping_add_rate', $this, $rate ); } /** * Get items in package. * * @param array $package Package of items from cart. * @return int */ public function get_package_item_qty( $package ) { $total_quantity = 0; foreach ( $package['contents'] as $item_id => $values ) { if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) { $total_quantity += $values['quantity']; } } return $total_quantity; } /** * Finds and returns shipping classes and the products with said class. * * @param mixed $package Package of items from cart. * @return array */ public function find_shipping_classes( $package ) { $found_shipping_classes = array(); foreach ( $package['contents'] as $item_id => $values ) { if ( $values['data']->needs_shipping() ) { $found_class = $values['data']->get_shipping_class(); if ( ! isset( $found_shipping_classes[ $found_class ] ) ) { $found_shipping_classes[ $found_class ] = array(); } $found_shipping_classes[ $found_class ][ $item_id ] = $values; } } return $found_shipping_classes; } /** * Sanitize the cost field. * * @since 3.4.0 * @param string $value Unsanitized value. * @throws Exception Last error triggered. * @return string */ public function sanitize_cost( $value ) { $value = is_null( $value ) ? '' : $value; $value = wp_kses_post( trim( wp_unslash( $value ) ) ); $value = str_replace( array( get_kkart_currency_symbol(), html_entity_decode( get_kkart_currency_symbol() ) ), '', $value ); // Thrown an error on the front end if the evaluate_cost will fail. $dummy_cost = $this->evaluate_cost( $value, array( 'cost' => 1, 'qty' => 1, ) ); if ( false === $dummy_cost ) { throw new Exception( KKART_Eval_Math::$last_error ); } return $value; } } PK!n,::9shipping/legacy-flat-rate/includes/settings-flat-rate.phpnu[10.00 * [qty].', 'kkart' ) . '
' . __( 'Supports the following placeholders: [qty] = number of items, [cost] = cost of items, [fee percent="10" min_fee="20"] = Percentage based fee.', 'kkart' ); /** * Settings for flat rate shipping. */ $settings = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Once disabled, this legacy method will no longer be available.', 'kkart' ), 'default' => 'no', ), 'title' => array( 'title' => __( 'Method title', 'kkart' ), 'type' => 'text', 'description' => __( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => __( 'Flat rate', 'kkart' ), 'desc_tip' => true, ), 'availability' => array( 'title' => __( 'Availability', 'kkart' ), 'type' => 'select', 'default' => 'all', 'class' => 'availability kkart-enhanced-select', 'options' => array( 'all' => __( 'All allowed countries', 'kkart' ), 'specific' => __( 'Specific Countries', 'kkart' ), ), ), 'countries' => array( 'title' => __( 'Specific countries', 'kkart' ), 'type' => 'multiselect', 'class' => 'kkart-enhanced-select', 'css' => 'width: 400px;', 'default' => '', 'options' => KKART()->countries->get_shipping_countries(), 'custom_attributes' => array( 'data-placeholder' => __( 'Select some countries', 'kkart' ), ), ), 'tax_status' => array( 'title' => __( 'Tax status', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'default' => 'taxable', 'options' => array( 'taxable' => __( 'Taxable', 'kkart' ), 'none' => _x( 'None', 'Tax status', 'kkart' ), ), ), 'cost' => array( 'title' => __( 'Cost', 'kkart' ), 'type' => 'text', 'placeholder' => '', 'description' => $cost_desc, 'default' => '', 'desc_tip' => true, ), ); $shipping_classes = KKART()->shipping()->get_shipping_classes(); if ( ! empty( $shipping_classes ) ) { $settings['class_costs'] = array( 'title' => __( 'Shipping class costs', 'kkart' ), 'type' => 'title', 'default' => '', /* translators: %s: Admin shipping settings URL */ 'description' => sprintf( __( 'These costs can optionally be added based on the product shipping class.', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=shipping§ion=classes' ) ), ); foreach ( $shipping_classes as $shipping_class ) { if ( ! isset( $shipping_class->term_id ) ) { continue; } $settings[ 'class_cost_' . $shipping_class->term_id ] = array( /* translators: %s: shipping class name */ 'title' => sprintf( __( '"%s" shipping class cost', 'kkart' ), esc_html( $shipping_class->name ) ), 'type' => 'text', 'placeholder' => __( 'N/A', 'kkart' ), 'description' => $cost_desc, 'default' => $this->get_option( 'class_cost_' . $shipping_class->slug ), // Before 2.5.0, we used slug here which caused issues with long setting names. 'desc_tip' => true, ); } $settings['no_class_cost'] = array( 'title' => __( 'No shipping class cost', 'kkart' ), 'type' => 'text', 'placeholder' => __( 'N/A', 'kkart' ), 'description' => $cost_desc, 'default' => '', 'desc_tip' => true, ); $settings['type'] = array( 'title' => __( 'Calculation type', 'kkart' ), 'type' => 'select', 'class' => 'kkart-enhanced-select', 'default' => 'class', 'options' => array( 'class' => __( 'Per class: Charge shipping for each shipping class individually', 'kkart' ), 'order' => __( 'Per order: Charge shipping for the most expensive shipping class', 'kkart' ), ), ); } if ( apply_filters( 'kkart_enable_deprecated_additional_flat_rates', $this->get_option( 'options', false ) ) ) { $settings['additional_rates'] = array( 'title' => __( 'Additional rates', 'kkart' ), 'type' => 'title', 'default' => '', 'description' => __( 'These rates are extra shipping options with additional costs (based on the flat rate).', 'kkart' ), ); $settings['options'] = array( 'title' => __( 'Additional rates', 'kkart' ), 'type' => 'textarea', 'description' => __( 'One per line: Option name | Additional cost [+- Percents] | Per cost type (order, class, or item) Example: Priority mail | 6.95 [+ 0.2%] | order.', 'kkart' ), 'default' => '', 'desc_tip' => true, 'placeholder' => __( 'Option name | Additional cost [+- Percents%] | Per cost type (order, class, or item)', 'kkart' ), ); } return $settings; PK!..Cshipping/legacy-flat-rate/class-kkart-shipping-legacy-flat-rate.phpnu[id = 'legacy_flat_rate'; $this->method_title = __( 'Flat rate (legacy)', 'kkart' ); /* translators: %s: Admin shipping settings URL */ $this->method_description = '' . sprintf( __( 'This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your Shipping zones.', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=shipping' ) ) . ''; $this->init(); add_action( 'kkart_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) ); add_action( 'kkart_flat_rate_shipping_add_rate', array( $this, 'calculate_extra_shipping' ), 10, 2 ); } /** * Process and redirect if disabled. */ public function process_admin_options() { parent::process_admin_options(); if ( 'no' === $this->settings['enabled'] ) { wp_redirect( admin_url( 'admin.php?page=kkart-settings&tab=shipping§ion=options' ) ); exit; } } /** * Return the name of the option in the WP DB. * * @since 2.6.0 * @return string */ public function get_option_key() { return $this->plugin_id . 'flat_rate_settings'; } /** * Init function. */ public function init() { // Load the settings. $this->init_form_fields(); $this->init_settings(); // Define user set variables. $this->title = $this->get_option( 'title' ); $this->availability = $this->get_option( 'availability' ); $this->countries = $this->get_option( 'countries' ); $this->tax_status = $this->get_option( 'tax_status' ); $this->cost = $this->get_option( 'cost' ); $this->type = $this->get_option( 'type', 'class' ); $this->options = $this->get_option( 'options', false ); // @deprecated 2.4.0 } /** * Initialise Settings Form Fields. */ public function init_form_fields() { $this->form_fields = include __DIR__ . '/includes/settings-flat-rate.php'; } /** * Evaluate a cost from a sum/string. * * @param string $sum Sum to evaluate. * @param array $args Arguments. * @return string */ protected function evaluate_cost( $sum, $args = array() ) { include_once KKART()->plugin_path() . '/includes/libraries/class-kkart-eval-math.php'; $locale = localeconv(); $decimals = array( kkart_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] ); $this->fee_cost = $args['cost']; // Expand shortcodes. add_shortcode( 'fee', array( $this, 'fee' ) ); $sum = do_shortcode( str_replace( array( '[qty]', '[cost]', ), array( $args['qty'], $args['cost'], ), $sum ) ); remove_shortcode( 'fee', array( $this, 'fee' ) ); // Remove whitespace from string. $sum = preg_replace( '/\s+/', '', $sum ); // Remove locale from string. $sum = str_replace( $decimals, '.', $sum ); // Trim invalid start/end characters. $sum = rtrim( ltrim( $sum, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" ); // Do the math. return $sum ? KKART_Eval_Math::evaluate( $sum ) : 0; } /** * Work out fee (shortcode). * * @param array $atts Shortcode attributes. * @return string */ public function fee( $atts ) { $atts = shortcode_atts( array( 'percent' => '', 'min_fee' => '', ), $atts, 'fee' ); $calculated_fee = 0; if ( $atts['percent'] ) { $calculated_fee = $this->fee_cost * ( floatval( $atts['percent'] ) / 100 ); } if ( $atts['min_fee'] && $calculated_fee < $atts['min_fee'] ) { $calculated_fee = $atts['min_fee']; } return $calculated_fee; } /** * Calculate shipping. * * @param array $package (default: array()). */ public function calculate_shipping( $package = array() ) { $rate = array( 'id' => $this->id, 'label' => $this->title, 'cost' => 0, 'package' => $package, ); // Calculate the costs. $has_costs = false; // True when a cost is set. False if all costs are blank strings. $cost = $this->get_option( 'cost' ); if ( '' !== $cost ) { $has_costs = true; $rate['cost'] = $this->evaluate_cost( $cost, array( 'qty' => $this->get_package_item_qty( $package ), 'cost' => $package['contents_cost'], ) ); } // Add shipping class costs. $found_shipping_classes = $this->find_shipping_classes( $package ); $highest_class_cost = 0; foreach ( $found_shipping_classes as $shipping_class => $products ) { // Also handles BW compatibility when slugs were used instead of ids. $shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' ); $class_cost_string = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' ); if ( '' === $class_cost_string ) { continue; } $has_costs = true; $class_cost = $this->evaluate_cost( $class_cost_string, array( 'qty' => array_sum( wp_list_pluck( $products, 'quantity' ) ), 'cost' => array_sum( wp_list_pluck( $products, 'line_total' ) ), ) ); if ( 'class' === $this->type ) { $rate['cost'] += $class_cost; } else { $highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost; } } if ( 'order' === $this->type && $highest_class_cost ) { $rate['cost'] += $highest_class_cost; } $rate['package'] = $package; // Add the rate. if ( $has_costs ) { $this->add_rate( $rate ); } /** * Developers can add additional flat rates based on this one via this action since @version 2.4. * * Previously there were (overly complex) options to add additional rates however this was not user. * friendly and goes against what Flat Rate Shipping was originally intended for. * * This example shows how you can add an extra rate based on this flat rate via custom function: * * add_action( 'kkart_flat_rate_shipping_add_rate', 'add_another_custom_flat_rate', 10, 2 ); * * function add_another_custom_flat_rate( $method, $rate ) { * $new_rate = $rate; * $new_rate['id'] .= ':' . 'custom_rate_name'; // Append a custom ID. * $new_rate['label'] = 'Rushed Shipping'; // Rename to 'Rushed Shipping'. * $new_rate['cost'] += 2; // Add $2 to the cost. * * // Add it to KKART. * $method->add_rate( $new_rate ); * }. */ do_action( 'kkart_flat_rate_shipping_add_rate', $this, $rate ); } /** * Get items in package. * * @param array $package Package information. * @return int */ public function get_package_item_qty( $package ) { $total_quantity = 0; foreach ( $package['contents'] as $item_id => $values ) { if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) { $total_quantity += $values['quantity']; } } return $total_quantity; } /** * Finds and returns shipping classes and the products with said class. * * @param mixed $package Package information. * @return array */ public function find_shipping_classes( $package ) { $found_shipping_classes = array(); foreach ( $package['contents'] as $item_id => $values ) { if ( $values['data']->needs_shipping() ) { $found_class = $values['data']->get_shipping_class(); if ( ! isset( $found_shipping_classes[ $found_class ] ) ) { $found_shipping_classes[ $found_class ] = array(); } $found_shipping_classes[ $found_class ][ $item_id ] = $values; } } return $found_shipping_classes; } /** * Adds extra calculated flat rates. * * @deprecated 2.4.0 * * Additional rates defined like this: * Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item). * * @param null $method Deprecated. * @param array $rate Rate information. */ public function calculate_extra_shipping( $method, $rate ) { if ( $this->options ) { $options = array_filter( (array) explode( "\n", $this->options ) ); foreach ( $options as $option ) { $this_option = array_map( 'trim', explode( KKART_DELIMITER, $option ) ); if ( count( $this_option ) !== 3 ) { continue; } $extra_rate = $rate; $extra_rate['id'] = $this->id . ':' . urldecode( sanitize_title( $this_option[0] ) ); $extra_rate['label'] = $this_option[0]; $extra_cost = $this->get_extra_cost( $this_option[1], $this_option[2], $rate['package'] ); if ( is_array( $extra_rate['cost'] ) ) { $extra_rate['cost']['order'] = $extra_rate['cost']['order'] + $extra_cost; } else { $extra_rate['cost'] += $extra_cost; } $this->add_rate( $extra_rate ); } } } /** * Calculate the percentage adjustment for each shipping rate. * * @deprecated 2.4.0 * @param float $cost Cost. * @param float $percent_adjustment Percent adjusment. * @param string $percent_operator Percent operator. * @param float $base_price Base price. * @return float */ public function calc_percentage_adjustment( $cost, $percent_adjustment, $percent_operator, $base_price ) { if ( '+' === $percent_operator ) { $cost += $percent_adjustment * $base_price; } else { $cost -= $percent_adjustment * $base_price; } return $cost; } /** * Get extra cost. * * @deprecated 2.4.0 * @param string $cost_string Cost string. * @param string $type Type. * @param array $package Package information. * @return float */ public function get_extra_cost( $cost_string, $type, $package ) { $cost = $cost_string; $cost_percent = false; // @codingStandardsIgnoreStart $pattern = '/' . // Start regex. '(\d+\.?\d*)' . // Capture digits, optionally capture a `.` and more digits. '\s*' . // Match whitespace. '(\+|-)' . // Capture the operand. '\s*' . // Match whitespace. '(\d+\.?\d*)' . // Capture digits, optionally capture a `.` and more digits. '\%/'; // Match the percent sign & end regex. // @codingStandardsIgnoreEnd if ( preg_match( $pattern, $cost_string, $this_cost_matches ) ) { $cost_operator = $this_cost_matches[2]; $cost_percent = $this_cost_matches[3] / 100; $cost = $this_cost_matches[1]; } switch ( $type ) { case 'class': $cost = $cost * count( $this->find_shipping_classes( $package ) ); break; case 'item': $cost = $cost * $this->get_package_item_qty( $package ); break; } if ( $cost_percent ) { switch ( $type ) { case 'class': $shipping_classes = $this->find_shipping_classes( $package ); foreach ( $shipping_classes as $shipping_class => $items ) { foreach ( $items as $item_id => $values ) { $cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] ); } } break; case 'item': foreach ( $package['contents'] as $item_id => $values ) { if ( $values['data']->needs_shipping() ) { $cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] ); } } break; case 'order': $cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $package['contents_cost'] ); break; } } return $cost; } } PK!{8class-kkart-order-refund.phpnu[ '', 'reason' => '', 'refunded_by' => 0, 'refunded_payment' => false, ); /** * Get internal type (post type.) * * @return string */ public function get_type() { return 'shop_order_refund'; } /** * Get status - always completed for refunds. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_status( $context = 'view' ) { return 'completed'; } /** * Get a title for the new post type. */ public function get_post_title() { // @codingStandardsIgnoreStart return sprintf( __( 'Refund – %s', 'kkart' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Order date parsed by strftime', 'kkart' ) ) ); // @codingStandardsIgnoreEnd } /** * Get refunded amount. * * @param string $context What the value is for. Valid values are view and edit. * @return int|float */ public function get_amount( $context = 'view' ) { return $this->get_prop( 'amount', $context ); } /** * Get refund reason. * * @since 2.2 * @param string $context What the value is for. Valid values are view and edit. * @return int|float */ public function get_reason( $context = 'view' ) { return $this->get_prop( 'reason', $context ); } /** * Get ID of user who did the refund. * * @since 3.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_refunded_by( $context = 'view' ) { return $this->get_prop( 'refunded_by', $context ); } /** * Return if the payment was refunded via API. * * @since 3.3 * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function get_refunded_payment( $context = 'view' ) { return $this->get_prop( 'refunded_payment', $context ); } /** * Get formatted refunded amount. * * @since 2.4 * @return string */ public function get_formatted_refund_amount() { return apply_filters( 'kkart_formatted_refund_amount', kkart_price( $this->get_amount(), array( 'currency' => $this->get_currency() ) ), $this ); } /** * Set refunded amount. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception if the amount is invalid. */ public function set_amount( $value ) { $this->set_prop( 'amount', kkart_format_decimal( $value ) ); } /** * Set refund reason. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception if the amount is invalid. */ public function set_reason( $value ) { $this->set_prop( 'reason', $value ); } /** * Set refunded by. * * @param int $value Value to set. * @throws KKART_Data_Exception Exception if the amount is invalid. */ public function set_refunded_by( $value ) { $this->set_prop( 'refunded_by', absint( $value ) ); } /** * Set if the payment was refunded via API. * * @since 3.3 * @param bool $value Value to set. */ public function set_refunded_payment( $value ) { $this->set_prop( 'refunded_payment', (bool) $value ); } /** * Magic __get method for backwards compatibility. * * @param string $key Value to get. * @return mixed */ public function __get( $key ) { kkart_doing_it_wrong( $key, 'Refund properties should not be accessed directly.', '3.0' ); /** * Maps legacy vars to new getters. */ if ( 'reason' === $key ) { return $this->get_reason(); } elseif ( 'refund_amount' === $key ) { return $this->get_amount(); } return parent::__get( $key ); } /** * Gets an refund from the database. * * @deprecated 3.0 * @param int $id (default: 0). * @return bool */ public function get_refund( $id = 0 ) { kkart_deprecated_function( 'get_refund', '3.0', 'read' ); if ( ! $id ) { return false; } $result = get_post( $id ); if ( $result ) { $this->populate( $result ); return true; } return false; } /** * Get refund amount. * * @deprecated 3.0 * @return int|float */ public function get_refund_amount() { kkart_deprecated_function( 'get_refund_amount', '3.0', 'get_amount' ); return $this->get_amount(); } /** * Get refund reason. * * @deprecated 3.0 * @return int|float */ public function get_refund_reason() { kkart_deprecated_function( 'get_refund_reason', '3.0', 'get_reason' ); return $this->get_reason(); } } PK!rϼZ)Z)class-kkart-geolocation.phpnu[ 'http://api.ipify.org/', 'ipecho' => 'http://ipecho.net/plain', 'ident' => 'http://ident.me', 'whatismyipaddress' => 'http://bot.whatismyipaddress.com', ); /** * API endpoints for geolocating an IP address * * @var array */ private static $geoip_apis = array( 'ipinfo.io' => 'https://ipinfo.io/%s/json', 'ip-api.com' => 'http://ip-api.com/json/%s', ); /** * Check if geolocation is enabled. * * @since 3.4.0 * @param string $current_settings Current geolocation settings. * @return bool */ private static function is_geolocation_enabled( $current_settings ) { return in_array( $current_settings, array( 'geolocation', 'geolocation_ajax' ), true ); } /** * Get current user IP Address. * * @return string */ public static function get_ip_address() { if ( isset( $_SERVER['HTTP_X_REAL_IP'] ) ) { return sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ) ); } elseif ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // Proxy servers can send through this header like this: X-Forwarded-For: client1, proxy1, proxy2 // Make sure we always only send through the first IP in the list which should always be the client IP. return (string) rest_is_ip_address( trim( current( preg_split( '/,/', sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) ) ) ) ); } elseif ( isset( $_SERVER['REMOTE_ADDR'] ) ) { return sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ); } return ''; } /** * Get user IP Address using an external service. * This can be used as a fallback for users on localhost where * get_ip_address() will be a local IP and non-geolocatable. * * @return string */ public static function get_external_ip_address() { $external_ip_address = '0.0.0.0'; if ( '' !== self::get_ip_address() ) { $transient_name = 'external_ip_address_' . self::get_ip_address(); $external_ip_address = get_transient( $transient_name ); } if ( false === $external_ip_address ) { $external_ip_address = '0.0.0.0'; $ip_lookup_services = apply_filters( 'kkart_geolocation_ip_lookup_apis', self::$ip_lookup_apis ); $ip_lookup_services_keys = array_keys( $ip_lookup_services ); shuffle( $ip_lookup_services_keys ); foreach ( $ip_lookup_services_keys as $service_name ) { $service_endpoint = $ip_lookup_services[ $service_name ]; $response = wp_safe_remote_get( $service_endpoint, array( 'timeout' => 2 ) ); if ( ! is_wp_error( $response ) && rest_is_ip_address( $response['body'] ) ) { $external_ip_address = apply_filters( 'kkart_geolocation_ip_lookup_api_response', kkart_clean( $response['body'] ), $service_name ); break; } } set_transient( $transient_name, $external_ip_address, WEEK_IN_SECONDS ); } return $external_ip_address; } /** * Geolocate an IP address. * * @param string $ip_address IP Address. * @param bool $fallback If true, fallbacks to alternative IP detection (can be slower). * @param bool $api_fallback If true, uses geolocation APIs if the database file doesn't exist (can be slower). * @return array */ public static function geolocate_ip( $ip_address = '', $fallback = false, $api_fallback = true ) { // Filter to allow custom geolocation of the IP address. $country_code = apply_filters( 'kkart_geolocate_ip', false, $ip_address, $fallback, $api_fallback ); if ( false !== $country_code ) { return array( 'country' => $country_code, 'state' => '', 'city' => '', 'postcode' => '', ); } if ( empty( $ip_address ) ) { $ip_address = self::get_ip_address(); } $country_code = self::get_country_code_from_headers(); /** * Get geolocation filter. * * @since 3.9.0 * @param array $geolocation Geolocation data, including country, state, city, and postcode. * @param string $ip_address IP Address. */ $geolocation = apply_filters( 'kkart_get_geolocation', array( 'country' => $country_code, 'state' => '', 'city' => '', 'postcode' => '', ), $ip_address ); // If we still haven't found a country code, let's consider doing an API lookup. if ( '' === $geolocation['country'] && $api_fallback ) { $geolocation['country'] = self::geolocate_via_api( $ip_address ); } // It's possible that we're in a local environment, in which case the geolocation needs to be done from the // external address. if ( '' === $geolocation['country'] && $fallback ) { $external_ip_address = self::get_external_ip_address(); // Only bother with this if the external IP differs. if ( '0.0.0.0' !== $external_ip_address && $external_ip_address !== $ip_address ) { return self::geolocate_ip( $external_ip_address, false, $api_fallback ); } } return array( 'country' => $geolocation['country'], 'state' => $geolocation['state'], 'city' => $geolocation['city'], 'postcode' => $geolocation['postcode'], ); } /** * Path to our local db. * * @deprecated 3.9.0 * @param string $deprecated Deprecated since 3.4.0. * @return string */ public static function get_local_database_path( $deprecated = '2' ) { kkart_deprecated_function( 'KKART_Geolocation::get_local_database_path', '3.9.0' ); $integration = kkart()->integrations->get_integration( 'maxmind_geolocation' ); return $integration->get_database_service()->get_database_path(); } /** * Update geoip database. * * @deprecated 3.9.0 * Extract files with PharData. Tool built into PHP since 5.3. */ public static function update_database() { kkart_deprecated_function( 'KKART_Geolocation::update_database', '3.9.0' ); $integration = kkart()->integrations->get_integration( 'maxmind_geolocation' ); $integration->update_database(); } /** * Fetches the country code from the request headers, if one is available. * * @since 3.9.0 * @return string The country code pulled from the headers, or empty string if one was not found. */ private static function get_country_code_from_headers() { $country_code = ''; $headers = array( 'MM_COUNTRY_CODE', 'GEOIP_COUNTRY_CODE', 'HTTP_CF_IPCOUNTRY', 'HTTP_X_COUNTRY_CODE', ); foreach ( $headers as $header ) { if ( empty( $_SERVER[ $header ] ) ) { continue; } $country_code = strtoupper( sanitize_text_field( wp_unslash( $_SERVER[ $header ] ) ) ); break; } return $country_code; } /** * Use APIs to Geolocate the user. * * Geolocation APIs can be added through the use of the kkart_geolocation_geoip_apis filter. * Provide a name=>value pair for service-slug=>endpoint. * * If APIs are defined, one will be chosen at random to fulfil the request. After completing, the result * will be cached in a transient. * * @param string $ip_address IP address. * @return string */ private static function geolocate_via_api( $ip_address ) { $country_code = get_transient( 'geoip_' . $ip_address ); if ( false === $country_code ) { $geoip_services = apply_filters( 'kkart_geolocation_geoip_apis', self::$geoip_apis ); if ( empty( $geoip_services ) ) { return ''; } $geoip_services_keys = array_keys( $geoip_services ); shuffle( $geoip_services_keys ); foreach ( $geoip_services_keys as $service_name ) { $service_endpoint = $geoip_services[ $service_name ]; $response = wp_safe_remote_get( sprintf( $service_endpoint, $ip_address ), array( 'timeout' => 2 ) ); if ( ! is_wp_error( $response ) && $response['body'] ) { switch ( $service_name ) { case 'ipinfo.io': $data = json_decode( $response['body'] ); $country_code = isset( $data->country ) ? $data->country : ''; break; case 'ip-api.com': $data = json_decode( $response['body'] ); $country_code = isset( $data->countryCode ) ? $data->countryCode : ''; // @codingStandardsIgnoreLine break; default: $country_code = apply_filters( 'kkart_geolocation_geoip_response_' . $service_name, '', $response['body'] ); break; } $country_code = sanitize_text_field( strtoupper( $country_code ) ); if ( $country_code ) { break; } } } set_transient( 'geoip_' . $ip_address, $country_code, WEEK_IN_SECONDS ); } return $country_code; } /** * Hook in geolocation functionality. * * @deprecated 3.9.0 * @return null */ public static function init() { kkart_deprecated_function( 'KKART_Geolocation::init', '3.9.0' ); return null; } /** * Prevent geolocation via MaxMind when using legacy versions of php. * * @deprecated 3.9.0 * @since 3.4.0 * @param string $default_customer_address current value. * @return string */ public static function disable_geolocation_on_legacy_php( $default_customer_address ) { kkart_deprecated_function( 'KKART_Geolocation::disable_geolocation_on_legacy_php', '3.9.0' ); if ( self::is_geolocation_enabled( $default_customer_address ) ) { $default_customer_address = 'base'; } return $default_customer_address; } /** * Maybe trigger a DB update for the first time. * * @deprecated 3.9.0 * @param string $new_value New value. * @param string $old_value Old value. * @return string */ public static function maybe_update_database( $new_value, $old_value ) { kkart_deprecated_function( 'KKART_Geolocation::maybe_update_database', '3.9.0' ); if ( $new_value !== $old_value && self::is_geolocation_enabled( $new_value ) ) { self::update_database(); } return $new_value; } } PK!class-kkart-embed.phpnu[' . $_product->get_price_html() . '

'; // WPCS: XSS ok. if ( ! empty( $post->post_excerpt ) ) { ob_start(); kkart_template_single_excerpt(); $excerpt = ob_get_clean(); } // Add the button. $excerpt .= self::product_buttons(); } return $excerpt; } /** * Create the button to go to the product page for embedded products. * * @since 2.4.11 * @return string */ public static function product_buttons() { $_product = kkart_get_product( get_the_ID() ); $buttons = array(); $button = '%s'; if ( $_product->is_type( 'simple' ) && $_product->is_purchasable() && $_product->is_in_stock() ) { $buttons[] = sprintf( $button, esc_url( add_query_arg( 'add-to-cart', get_the_ID(), kkart_get_cart_url() ) ), esc_html__( 'Buy now', 'kkart' ) ); } $buttons[] = sprintf( $button, get_the_permalink(), esc_html__( 'Read more', 'kkart' ) ); return '

' . implode( ' ', $buttons ) . '

'; } /** * Prints the markup for the rating stars. * * @since 2.4.11 */ public static function get_ratings() { // Make sure we're only affecting embedded products. if ( ! self::is_embedded_product() ) { return; } $_product = kkart_get_product( get_the_ID() ); if ( $_product && $_product->get_average_rating() > 0 ) { ?>
get_average_rating() ) ); ?>
prefix = 'wp_' . get_current_blog_id(); $this->action = 'kkart_emailer'; // Dispatch queue after shutdown. add_action( 'shutdown', array( $this, 'dispatch_queue' ), 100 ); parent::__construct(); } /** * Schedule fallback event. */ protected function schedule_event() { if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) { wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier ); } } /** * Task * * Override this method to perform any actions required on each * queue item. Return the modified item for further processing * in the next pass through. Or, return false to remove the * item from the queue. * * @param array $callback Update callback function. * @return mixed */ protected function task( $callback ) { if ( isset( $callback['filter'], $callback['args'] ) ) { try { KKART_Emails::send_queued_transactional_email( $callback['filter'], $callback['args'] ); } catch ( Exception $e ) { if ( Constants::is_true( 'WP_DEBUG' ) ) { trigger_error( 'Transactional email triggered fatal error for callback ' . esc_html( $callback['filter'] ), E_USER_WARNING ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_trigger_error } } } return false; } /** * Finishes replying to the client, but keeps the process running for further (async) code execution. * * @see https://core.trac.wordpress.org/ticket/41358 . */ protected function close_http_connection() { // Only 1 PHP process can access a session object at a time, close this so the next request isn't kept waiting. // @codingStandardsIgnoreStart if ( session_id() ) { session_write_close(); } // @codingStandardsIgnoreEnd kkart_set_time_limit( 0 ); // fastcgi_finish_request is the cleanest way to send the response and keep the script running, but not every server has it. if ( is_callable( 'fastcgi_finish_request' ) ) { fastcgi_finish_request(); } else { // Fallback: send headers and flush buffers. if ( ! headers_sent() ) { header( 'Connection: close' ); } @ob_end_flush(); // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged flush(); } } /** * Save and run queue. */ public function dispatch_queue() { if ( ! empty( $this->data ) ) { $this->close_http_connection(); $this->save()->dispatch(); } } /** * Get post args * * @return array */ protected function get_post_args() { if ( property_exists( $this, 'post_args' ) ) { return $this->post_args; } // Pass cookies through with the request so nonces function. $cookies = array(); foreach ( $_COOKIE as $name => $value ) { // WPCS: input var ok. if ( 'PHPSESSID' === $name ) { continue; } $cookies[] = new WP_Http_Cookie( array( 'name' => $name, 'value' => $value, ) ); } return array( 'timeout' => 0.01, 'blocking' => false, 'body' => $this->data, 'cookies' => $cookies, 'sslverify' => apply_filters( 'https_local_ssl_verify', false ), ); } /** * Handle * * Pass each queue item to the task handler, while remaining * within server memory and time limit constraints. */ protected function handle() { $this->lock_process(); do { $batch = $this->get_batch(); if ( empty( $batch->data ) ) { break; } foreach ( $batch->data as $key => $value ) { $task = $this->task( $value ); if ( false !== $task ) { $batch->data[ $key ] = $task; } else { unset( $batch->data[ $key ] ); } // Update batch before sending more to prevent duplicate email possibility. $this->update( $batch->key, $batch->data ); if ( $this->time_exceeded() || $this->memory_exceeded() ) { // Batch limits reached. break; } } if ( empty( $batch->data ) ) { $this->delete( $batch->key ); } } while ( ! $this->time_exceeded() && ! $this->memory_exceeded() && ! $this->is_queue_empty() ); $this->unlock_process(); // Start next batch or complete process. if ( ! $this->is_queue_empty() ) { $this->dispatch(); } else { $this->complete(); } } } PK! class name. * Example: 'product' => 'KKART_Product_Data_Store_CPT' * You can also pass something like product_ for product stores and * that type will be used first when available, if a store is requested like * this and doesn't exist, then the store would fall back to 'product'. * Ran through `kkart_data_stores`. * * @var array */ private $stores = array( 'coupon' => 'KKART_Coupon_Data_Store_CPT', 'customer' => 'KKART_Customer_Data_Store', 'customer-download' => 'KKART_Customer_Download_Data_Store', 'customer-download-log' => 'KKART_Customer_Download_Log_Data_Store', 'customer-session' => 'KKART_Customer_Data_Store_Session', 'order' => 'KKART_Order_Data_Store_CPT', 'order-refund' => 'KKART_Order_Refund_Data_Store_CPT', 'order-item' => 'KKART_Order_Item_Data_Store', 'order-item-coupon' => 'KKART_Order_Item_Coupon_Data_Store', 'order-item-fee' => 'KKART_Order_Item_Fee_Data_Store', 'order-item-product' => 'KKART_Order_Item_Product_Data_Store', 'order-item-shipping' => 'KKART_Order_Item_Shipping_Data_Store', 'order-item-tax' => 'KKART_Order_Item_Tax_Data_Store', 'payment-token' => 'KKART_Payment_Token_Data_Store', 'product' => 'KKART_Product_Data_Store_CPT', 'product-grouped' => 'KKART_Product_Grouped_Data_Store_CPT', 'product-variable' => 'KKART_Product_Variable_Data_Store_CPT', 'product-variation' => 'KKART_Product_Variation_Data_Store_CPT', 'shipping-zone' => 'KKART_Shipping_Zone_Data_Store', 'webhook' => 'KKART_Webhook_Data_Store', ); /** * Contains the name of the current data store's class name. * * @var string */ private $current_class_name = ''; /** * The object type this store works with. * * @var string */ private $object_type = ''; /** * Tells KKART_Data_Store which object (coupon, product, order, etc) * store we want to work with. * * @throws Exception When validation fails. * @param string $object_type Name of object. */ public function __construct( $object_type ) { $this->object_type = $object_type; $this->stores = apply_filters( 'kkart_data_stores', $this->stores ); // If this object type can't be found, check to see if we can load one // level up (so if product-type isn't found, we try product). if ( ! array_key_exists( $object_type, $this->stores ) ) { $pieces = explode( '-', $object_type ); $object_type = $pieces[0]; } if ( array_key_exists( $object_type, $this->stores ) ) { $store = apply_filters( 'kkart_' . $object_type . '_data_store', $this->stores[ $object_type ] ); if ( is_object( $store ) ) { if ( ! $store instanceof KKART_Object_Data_Store_Interface ) { throw new Exception( __( 'Invalid data store.', 'kkart' ) ); } $this->current_class_name = get_class( $store ); $this->instance = $store; } else { if ( ! class_exists( $store ) ) { throw new Exception( __( 'Invalid data store.', 'kkart' ) ); } $this->current_class_name = $store; $this->instance = new $store(); } } else { throw new Exception( __( 'Invalid data store.', 'kkart' ) ); } } /** * Only store the object type to avoid serializing the data store instance. * * @return array */ public function __sleep() { return array( 'object_type' ); } /** * Re-run the constructor with the object type. * * @throws Exception When validation fails. */ public function __wakeup() { $this->__construct( $this->object_type ); } /** * Loads a data store. * * @param string $object_type Name of object. * * @since 3.0.0 * @throws Exception When validation fails. * @return KKART_Data_Store */ public static function load( $object_type ) { return new KKART_Data_Store( $object_type ); } /** * Returns the class name of the current data store. * * @since 3.0.0 * @return string */ public function get_current_class_name() { return $this->current_class_name; } /** * Reads an object from the data store. * * @since 3.0.0 * @param KKART_Data $data Kkart data instance. */ public function read( &$data ) { $this->instance->read( $data ); } /** * Create an object in the data store. * * @since 3.0.0 * @param KKART_Data $data Kkart data instance. */ public function create( &$data ) { $this->instance->create( $data ); } /** * Update an object in the data store. * * @since 3.0.0 * @param KKART_Data $data Kkart data instance. */ public function update( &$data ) { $this->instance->update( $data ); } /** * Delete an object from the data store. * * @since 3.0.0 * @param KKART_Data $data Kkart data instance. * @param array $args Array of args to pass to the delete method. */ public function delete( &$data, $args = array() ) { $this->instance->delete( $data, $args ); } /** * Data stores can define additional functions (for example, coupons have * some helper methods for increasing or decreasing usage). This passes * through to the instance if that function exists. * * @since 3.0.0 * @param string $method Method. * @param mixed $parameters Parameters. * @return mixed */ public function __call( $method, $parameters ) { if ( is_callable( array( $this->instance, $method ) ) ) { $object = array_shift( $parameters ); $parameters = array_merge( array( &$object ), $parameters ); return $this->instance->$method( ...$parameters ); } } } PK!x "class-kkart-background-updater.phpnu[prefix = 'wp_' . get_current_blog_id(); $this->action = 'kkart_updater'; parent::__construct(); } /** * Dispatch updater. * * Updater will still run via cron job if this fails for any reason. */ public function dispatch() { $dispatched = parent::dispatch(); $logger = kkart_get_logger(); if ( is_wp_error( $dispatched ) ) { $logger->error( sprintf( 'Unable to dispatch Kkart updater: %s', $dispatched->get_error_message() ), array( 'source' => 'kkart_db_updates' ) ); } } /** * Handle cron healthcheck * * Restart the background process if not already running * and data exists in the queue. */ public function handle_cron_healthcheck() { if ( $this->is_process_running() ) { // Background process already running. return; } if ( $this->is_queue_empty() ) { // No data to process. $this->clear_scheduled_event(); return; } $this->handle(); } /** * Schedule fallback event. */ protected function schedule_event() { if ( ! wp_next_scheduled( $this->cron_hook_identifier ) ) { wp_schedule_event( time() + 10, $this->cron_interval_identifier, $this->cron_hook_identifier ); } } /** * Is the updater running? * * @return boolean */ public function is_updating() { return false === $this->is_queue_empty(); } /** * Task * * Override this method to perform any actions required on each * queue item. Return the modified item for further processing * in the next pass through. Or, return false to remove the * item from the queue. * * @param string $callback Update callback function. * @return string|bool */ protected function task( $callback ) { kkart_maybe_define_constant( 'KKART_UPDATING', true ); $logger = kkart_get_logger(); include_once dirname( __FILE__ ) . '/kkart-update-functions.php'; $result = false; if ( is_callable( $callback ) ) { $logger->info( sprintf( 'Running %s callback', $callback ), array( 'source' => 'kkart_db_updates' ) ); $result = (bool) call_user_func( $callback, $this ); if ( $result ) { $logger->info( sprintf( '%s callback needs to run again', $callback ), array( 'source' => 'kkart_db_updates' ) ); } else { $logger->info( sprintf( 'Finished running %s callback', $callback ), array( 'source' => 'kkart_db_updates' ) ); } } else { $logger->notice( sprintf( 'Could not find %s callback', $callback ), array( 'source' => 'kkart_db_updates' ) ); } return $result ? $callback : false; } /** * Complete * * Override if applicable, but ensure that the below actions are * performed, or, call parent::complete(). */ protected function complete() { $logger = kkart_get_logger(); $logger->info( 'Data update complete', array( 'source' => 'kkart_db_updates' ) ); KKART_Install::update_db_version(); parent::complete(); } /** * See if the batch limit has been exceeded. * * @return bool */ public function is_memory_exceeded() { return $this->memory_exceeded(); } } PK!#z8z8!class-kkart-privacy-exporters.phpnu[ 'kkart_customer', 'group_label' => __( 'Customer Data', 'kkart' ), 'group_description' => __( 'User’s Kkart customer data.', 'kkart' ), 'item_id' => 'user', 'data' => $customer_personal_data, ); } } return array( 'data' => $data_to_export, 'done' => true, ); } /** * Finds and exports data which could be used to identify a person from Kkart data associated with an email address. * * Orders are exported in blocks of 10 to avoid timeouts. * * @since 3.4.0 * @param string $email_address The user email address. * @param int $page Page. * @return array An array of personal data in name value pairs */ public static function order_data_exporter( $email_address, $page ) { $done = true; $page = (int) $page; $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. $data_to_export = array(); $order_query = array( 'limit' => 10, 'page' => $page, 'customer' => array( $email_address ), ); if ( $user instanceof WP_User ) { $order_query['customer'][] = (int) $user->ID; } $orders = kkart_get_orders( $order_query ); if ( 0 < count( $orders ) ) { foreach ( $orders as $order ) { $data_to_export[] = array( 'group_id' => 'kkart_orders', 'group_label' => __( 'Orders', 'kkart' ), 'group_description' => __( 'User’s Kkart orders data.', 'kkart' ), 'item_id' => 'order-' . $order->get_id(), 'data' => self::get_order_personal_data( $order ), ); } $done = 10 > count( $orders ); } return array( 'data' => $data_to_export, 'done' => $done, ); } /** * Finds and exports customer download logs by email address. * * @since 3.4.0 * @param string $email_address The user email address. * @param int $page Page. * @throws Exception When KKART_Data_Store validation fails. * @return array An array of personal data in name value pairs */ public static function download_data_exporter( $email_address, $page ) { $done = true; $page = (int) $page; $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. $data_to_export = array(); $downloads_query = array( 'limit' => 10, 'page' => $page, ); if ( $user instanceof WP_User ) { $downloads_query['user_id'] = (int) $user->ID; } else { $downloads_query['user_email'] = $email_address; } $customer_download_data_store = KKART_Data_Store::load( 'customer-download' ); $customer_download_log_data_store = KKART_Data_Store::load( 'customer-download-log' ); $downloads = $customer_download_data_store->get_downloads( $downloads_query ); if ( 0 < count( $downloads ) ) { foreach ( $downloads as $download ) { $data_to_export[] = array( 'group_id' => 'kkart_downloads', /* translators: This is the headline for a list of downloads purchased from the store for a given user. */ 'group_label' => __( 'Purchased Downloads', 'kkart' ), 'group_description' => __( 'User’s Kkart purchased downloads data.', 'kkart' ), 'item_id' => 'download-' . $download->get_id(), 'data' => self::get_download_personal_data( $download ), ); $download_logs = $customer_download_log_data_store->get_download_logs_for_permission( $download->get_id() ); foreach ( $download_logs as $download_log ) { $data_to_export[] = array( 'group_id' => 'kkart_download_logs', /* translators: This is the headline for a list of access logs for downloads purchased from the store for a given user. */ 'group_label' => __( 'Access to Purchased Downloads', 'kkart' ), 'group_description' => __( 'User’s Kkart access to purchased downloads data.', 'kkart' ), 'item_id' => 'download-log-' . $download_log->get_id(), 'data' => array( array( 'name' => __( 'Download ID', 'kkart' ), 'value' => $download_log->get_permission_id(), ), array( 'name' => __( 'Timestamp', 'kkart' ), 'value' => $download_log->get_timestamp(), ), array( 'name' => __( 'IP Address', 'kkart' ), 'value' => $download_log->get_user_ip_address(), ), ), ); } } $done = 10 > count( $downloads ); } return array( 'data' => $data_to_export, 'done' => $done, ); } /** * Get personal data (key/value pairs) for a user object. * * @since 3.4.0 * @param WP_User $user user object. * @throws Exception If customer cannot be read/found and $data is set to KKART_Customer class. * @return array */ protected static function get_customer_personal_data( $user ) { $personal_data = array(); $customer = new KKART_Customer( $user->ID ); if ( ! $customer ) { return array(); } $props_to_export = apply_filters( 'kkart_privacy_export_customer_personal_data_props', array( 'billing_first_name' => __( 'Billing First Name', 'kkart' ), 'billing_last_name' => __( 'Billing Last Name', 'kkart' ), 'billing_company' => __( 'Billing Company', 'kkart' ), 'billing_address_1' => __( 'Billing Address 1', 'kkart' ), 'billing_address_2' => __( 'Billing Address 2', 'kkart' ), 'billing_city' => __( 'Billing City', 'kkart' ), 'billing_postcode' => __( 'Billing Postal/Zip Code', 'kkart' ), 'billing_state' => __( 'Billing State', 'kkart' ), 'billing_country' => __( 'Billing Country / Region', 'kkart' ), 'billing_phone' => __( 'Phone Number', 'kkart' ), 'billing_email' => __( 'Email Address', 'kkart' ), 'shipping_first_name' => __( 'Shipping First Name', 'kkart' ), 'shipping_last_name' => __( 'Shipping Last Name', 'kkart' ), 'shipping_company' => __( 'Shipping Company', 'kkart' ), 'shipping_address_1' => __( 'Shipping Address 1', 'kkart' ), 'shipping_address_2' => __( 'Shipping Address 2', 'kkart' ), 'shipping_city' => __( 'Shipping City', 'kkart' ), 'shipping_postcode' => __( 'Shipping Postal/Zip Code', 'kkart' ), 'shipping_state' => __( 'Shipping State', 'kkart' ), 'shipping_country' => __( 'Shipping Country / Region', 'kkart' ), ), $customer ); foreach ( $props_to_export as $prop => $description ) { $value = ''; if ( is_callable( array( $customer, 'get_' . $prop ) ) ) { $value = $customer->{"get_$prop"}( 'edit' ); } $value = apply_filters( 'kkart_privacy_export_customer_personal_data_prop_value', $value, $prop, $customer ); if ( $value ) { $personal_data[] = array( 'name' => $description, 'value' => $value, ); } } /** * Allow extensions to register their own personal data for this customer for the export. * * @since 3.4.0 * @param array $personal_data Array of name value pairs. * @param KKART_Order $order A customer object. */ $personal_data = apply_filters( 'kkart_privacy_export_customer_personal_data', $personal_data, $customer ); return $personal_data; } /** * Get personal data (key/value pairs) for an order object. * * @since 3.4.0 * @param KKART_Order $order Order object. * @return array */ protected static function get_order_personal_data( $order ) { $personal_data = array(); $props_to_export = apply_filters( 'kkart_privacy_export_order_personal_data_props', array( 'order_number' => __( 'Order Number', 'kkart' ), 'date_created' => __( 'Order Date', 'kkart' ), 'total' => __( 'Order Total', 'kkart' ), 'items' => __( 'Items Purchased', 'kkart' ), 'customer_ip_address' => __( 'IP Address', 'kkart' ), 'customer_user_agent' => __( 'Browser User Agent', 'kkart' ), 'formatted_billing_address' => __( 'Billing Address', 'kkart' ), 'formatted_shipping_address' => __( 'Shipping Address', 'kkart' ), 'billing_phone' => __( 'Phone Number', 'kkart' ), 'billing_email' => __( 'Email Address', 'kkart' ), ), $order ); foreach ( $props_to_export as $prop => $name ) { $value = ''; switch ( $prop ) { case 'items': $item_names = array(); foreach ( $order->get_items() as $item ) { $item_names[] = $item->get_name() . ' x ' . $item->get_quantity(); } $value = implode( ', ', $item_names ); break; case 'date_created': $value = kkart_format_datetime( $order->get_date_created(), get_option( 'date_format' ) . ', ' . get_option( 'time_format' ) ); break; case 'formatted_billing_address': case 'formatted_shipping_address': $value = preg_replace( '##i', ', ', $order->{"get_$prop"}() ); break; default: if ( is_callable( array( $order, 'get_' . $prop ) ) ) { $value = $order->{"get_$prop"}(); } break; } $value = apply_filters( 'kkart_privacy_export_order_personal_data_prop', $value, $prop, $order ); if ( $value ) { $personal_data[] = array( 'name' => $name, 'value' => $value, ); } } // Export meta data. $meta_to_export = apply_filters( 'kkart_privacy_export_order_personal_data_meta', array( 'Payer first name' => __( 'Payer first name', 'kkart' ), 'Payer last name' => __( 'Payer last name', 'kkart' ), 'Payer PayPal address' => __( 'Payer PayPal address', 'kkart' ), 'Transaction ID' => __( 'Transaction ID', 'kkart' ), ) ); if ( ! empty( $meta_to_export ) && is_array( $meta_to_export ) ) { foreach ( $meta_to_export as $meta_key => $name ) { $value = apply_filters( 'kkart_privacy_export_order_personal_data_meta_value', $order->get_meta( $meta_key ), $meta_key, $order ); if ( $value ) { $personal_data[] = array( 'name' => $name, 'value' => $value, ); } } } /** * Allow extensions to register their own personal data for this order for the export. * * @since 3.4.0 * @param array $personal_data Array of name value pairs to expose in the export. * @param KKART_Order $order An order object. */ $personal_data = apply_filters( 'kkart_privacy_export_order_personal_data', $personal_data, $order ); return $personal_data; } /** * Get personal data (key/value pairs) for a download object. * * @since 3.4.0 * @param KKART_Order $download Download object. * @return array */ protected static function get_download_personal_data( $download ) { $personal_data = array( array( 'name' => __( 'Download ID', 'kkart' ), 'value' => $download->get_id(), ), array( 'name' => __( 'Order ID', 'kkart' ), 'value' => $download->get_order_id(), ), array( 'name' => __( 'Product', 'kkart' ), 'value' => get_the_title( $download->get_product_id() ), ), array( 'name' => __( 'User email', 'kkart' ), 'value' => $download->get_user_email(), ), array( 'name' => __( 'Downloads remaining', 'kkart' ), 'value' => $download->get_downloads_remaining(), ), array( 'name' => __( 'Download count', 'kkart' ), 'value' => $download->get_download_count(), ), array( 'name' => __( 'Access granted', 'kkart' ), 'value' => date( 'Y-m-d', $download->get_access_granted( 'edit' )->getTimestamp() ), ), array( 'name' => __( 'Access expires', 'kkart' ), 'value' => ! is_null( $download->get_access_expires( 'edit' ) ) ? date( 'Y-m-d', $download->get_access_expires( 'edit' )->getTimestamp() ) : null, ), ); /** * Allow extensions to register their own personal data for this download for the export. * * @since 3.4.0 * @param array $personal_data Array of name value pairs to expose in the export. * @param KKART_Order $order An order object. */ $personal_data = apply_filters( 'kkart_privacy_export_download_personal_data', $personal_data, $download ); return $personal_data; } /** * Finds and exports payment tokens by email address for a customer. * * @since 3.4.0 * @param string $email_address The user email address. * @param int $page Page. * @return array An array of personal data in name value pairs */ public static function customer_tokens_exporter( $email_address, $page ) { $user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data. $data_to_export = array(); if ( ! $user instanceof WP_User ) { return array( 'data' => $data_to_export, 'done' => true, ); } $tokens = KKART_Payment_Tokens::get_tokens( array( 'user_id' => $user->ID, 'limit' => 10, 'page' => $page, ) ); if ( 0 < count( $tokens ) ) { foreach ( $tokens as $token ) { $data_to_export[] = array( 'group_id' => 'kkart_tokens', 'group_label' => __( 'Payment Tokens', 'kkart' ), 'group_description' => __( 'User’s Kkart payment tokens data.', 'kkart' ), 'item_id' => 'token-' . $token->get_id(), 'data' => array( array( 'name' => __( 'Token', 'kkart' ), 'value' => $token->get_display_name(), ), ), ); } $done = 10 > count( $tokens ); } else { $done = true; } return array( 'data' => $data_to_export, 'done' => $done, ); } } PK!?Ʊ Z Zclass-kkart-tracker.phpnu[ apply_filters( 'kkart_tracker_last_send_interval', strtotime( '-1 week' ) ) ) { return; } } else { // Make sure there is at least a 1 hour delay between override sends, we don't want duplicate calls due to double clicking links. $last_send = self::get_last_send_time(); if ( $last_send && $last_send > strtotime( '-1 hours' ) ) { return; } } // Update time first before sending to ensure it is set. update_option( 'kkart_tracker_last_send', time() ); $params = self::get_tracking_data(); wp_safe_remote_post( self::$api_url, array( 'method' => 'POST', 'timeout' => 45, 'redirection' => 5, 'httpversion' => '1.0', 'blocking' => false, 'headers' => array( 'user-agent' => 'KkartTracker/' . md5( esc_url_raw( home_url( '/' ) ) ) . ';' ), 'body' => wp_json_encode( $params ), 'cookies' => array(), ) ); } /** * Get the last time tracking data was sent. * * @return int|bool */ private static function get_last_send_time() { return apply_filters( 'kkart_tracker_last_send_time', get_option( 'kkart_tracker_last_send', false ) ); } /** * Test whether this site is a staging site according to the Jetpack criteria. * * With Jetpack 8.1+, Jetpack::is_staging_site has been deprecated. * \Automattic\Jetpack\Status::is_staging_site is the replacement. * However, there are version of JP where \Automattic\Jetpack\Status exists, but does *not* contain is_staging_site method, * so with those, code still needs to use the previous check as a fallback. * * @return bool */ private static function is_jetpack_staging_site() { if ( class_exists( '\Automattic\Jetpack\Status' ) ) { // Preferred way of checking with Jetpack 8.1+. $jp_status = new \Automattic\Jetpack\Status(); if ( is_callable( array( $jp_status, 'is_staging_site' ) ) ) { return $jp_status->is_staging_site(); } } return ( class_exists( 'Jetpack' ) && is_callable( 'Jetpack::is_staging_site' ) && Jetpack::is_staging_site() ); } /** * Get all the tracking data. * * @return array */ private static function get_tracking_data() { $data = array(); // General site info. $data['url'] = home_url(); $data['email'] = apply_filters( 'kkart_tracker_admin_email', get_option( 'admin_email' ) ); $data['theme'] = self::get_theme_info(); // WordPress Info. $data['wp'] = self::get_wordpress_info(); // Server Info. $data['server'] = self::get_server_info(); // Plugin info. $all_plugins = self::get_all_plugins(); $data['active_plugins'] = $all_plugins['active_plugins']; $data['inactive_plugins'] = $all_plugins['inactive_plugins']; // Jetpack & Kkart Connect. $data['jetpack_version'] = Constants::is_defined( 'JETPACK__VERSION' ) ? Constants::get_constant( 'JETPACK__VERSION' ) : 'none'; $data['jetpack_connected'] = ( class_exists( 'Jetpack' ) && is_callable( 'Jetpack::is_active' ) && Jetpack::is_active() ) ? 'yes' : 'no'; $data['jetpack_is_staging'] = self::is_jetpack_staging_site() ? 'yes' : 'no'; $data['connect_installed'] = class_exists( 'KKART_Connect_Loader' ) ? 'yes' : 'no'; $data['connect_active'] = ( class_exists( 'KKART_Connect_Loader' ) && wp_next_scheduled( 'kkart_connect_fetch_service_schemas' ) ) ? 'yes' : 'no'; $data['helper_connected'] = self::get_helper_connected(); // Store count info. $data['users'] = self::get_user_counts(); $data['products'] = self::get_product_counts(); $data['orders'] = self::get_orders(); $data['reviews'] = self::get_review_counts(); $data['categories'] = self::get_category_counts(); // Payment gateway info. $data['gateways'] = self::get_active_payment_gateways(); // Shipping method info. $data['shipping_methods'] = self::get_active_shipping_methods(); // Get all Kkart options info. $data['settings'] = self::get_all_kkart_options_values(); // Template overrides. $data['template_overrides'] = self::get_all_template_overrides(); // Template overrides. $data['admin_user_agents'] = self::get_admin_user_agents(); // Cart & checkout tech (blocks or shortcodes). $data['cart_checkout'] = self::get_cart_checkout_info(); return apply_filters( 'kkart_tracker_data', $data ); } /** * Get the current theme info, theme name and version. * * @return array */ public static function get_theme_info() { $theme_data = wp_get_theme(); $theme_child_theme = kkart_bool_to_string( is_child_theme() ); $theme_kkart_support = kkart_bool_to_string( current_theme_supports( 'kkart' ) ); return array( 'name' => $theme_data->Name, // @phpcs:ignore 'version' => $theme_data->Version, // @phpcs:ignore 'child_theme' => $theme_child_theme, 'kkart_support' => $theme_kkart_support, ); } /** * Get WordPress related data. * * @return array */ private static function get_wordpress_info() { $wp_data = array(); $memory = kkart_let_to_num( WP_MEMORY_LIMIT ); if ( function_exists( 'memory_get_usage' ) ) { $system_memory = kkart_let_to_num( @ini_get( 'memory_limit' ) ); $memory = max( $memory, $system_memory ); } // WordPress 5.5+ environment type specification. // 'production' is the default in WP, thus using it as a default here, too. $environment_type = 'production'; if ( function_exists( 'wp_get_environment_type' ) ) { $environment_type = wp_get_environment_type(); } $wp_data['memory_limit'] = size_format( $memory ); $wp_data['debug_mode'] = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? 'Yes' : 'No'; $wp_data['locale'] = get_locale(); $wp_data['version'] = get_bloginfo( 'version' ); $wp_data['multisite'] = is_multisite() ? 'Yes' : 'No'; $wp_data['env_type'] = $environment_type; return $wp_data; } /** * Get server related info. * * @return array */ private static function get_server_info() { $server_data = array(); if ( ! empty( $_SERVER['SERVER_SOFTWARE'] ) ) { $server_data['software'] = $_SERVER['SERVER_SOFTWARE']; // @phpcs:ignore } if ( function_exists( 'phpversion' ) ) { $server_data['php_version'] = phpversion(); } if ( function_exists( 'ini_get' ) ) { $server_data['php_post_max_size'] = size_format( kkart_let_to_num( ini_get( 'post_max_size' ) ) ); $server_data['php_time_limt'] = ini_get( 'max_execution_time' ); $server_data['php_max_input_vars'] = ini_get( 'max_input_vars' ); $server_data['php_suhosin'] = extension_loaded( 'suhosin' ) ? 'Yes' : 'No'; } $database_version = kkart_get_server_database_version(); $server_data['mysql_version'] = $database_version['number']; $server_data['php_max_upload_size'] = size_format( wp_max_upload_size() ); $server_data['php_default_timezone'] = date_default_timezone_get(); $server_data['php_soap'] = class_exists( 'SoapClient' ) ? 'Yes' : 'No'; $server_data['php_fsockopen'] = function_exists( 'fsockopen' ) ? 'Yes' : 'No'; $server_data['php_curl'] = function_exists( 'curl_init' ) ? 'Yes' : 'No'; return $server_data; } /** * Get all plugins grouped into activated or not. * * @return array */ private static function get_all_plugins() { // Ensure get_plugins function is loaded. if ( ! function_exists( 'get_plugins' ) ) { include KKART_ADMIN_DIR . 'includes/plugin.php'; } $plugins = get_plugins(); $active_plugins_keys = get_option( 'active_plugins', array() ); $active_plugins = array(); foreach ( $plugins as $k => $v ) { // Take care of formatting the data how we want it. $formatted = array(); $formatted['name'] = strip_tags( $v['Name'] ); if ( isset( $v['Version'] ) ) { $formatted['version'] = strip_tags( $v['Version'] ); } if ( isset( $v['Author'] ) ) { $formatted['author'] = strip_tags( $v['Author'] ); } if ( isset( $v['Network'] ) ) { $formatted['network'] = strip_tags( $v['Network'] ); } if ( isset( $v['PluginURI'] ) ) { $formatted['plugin_uri'] = strip_tags( $v['PluginURI'] ); } if ( in_array( $k, $active_plugins_keys ) ) { // Remove active plugins from list so we can show active and inactive separately. unset( $plugins[ $k ] ); $active_plugins[ $k ] = $formatted; } else { $plugins[ $k ] = $formatted; } } return array( 'active_plugins' => $active_plugins, 'inactive_plugins' => $plugins, ); } /** * Check to see if the helper is connected to kkart.com * * @return string */ private static function get_helper_connected() { if ( class_exists( 'KKART_Helper_Options' ) && is_callable( 'KKART_Helper_Options::get' ) ) { $authenticated = KKART_Helper_Options::get( 'auth' ); } else { $authenticated = ''; } return ( ! empty( $authenticated ) ) ? 'yes' : 'no'; } /** * Get user totals based on user role. * * @return array */ private static function get_user_counts() { $user_count = array(); $user_count_data = count_users(); $user_count['total'] = $user_count_data['total_users']; // Get user count based on user role. foreach ( $user_count_data['avail_roles'] as $role => $count ) { $user_count[ $role ] = $count; } return $user_count; } /** * Get product totals based on product type. * * @return array */ public static function get_product_counts() { $product_count = array(); $product_count_data = wp_count_posts( 'product' ); $product_count['total'] = $product_count_data->publish; $product_statuses = get_terms( 'product_type', array( 'hide_empty' => 0 ) ); foreach ( $product_statuses as $product_status ) { $product_count[ $product_status->name ] = $product_status->count; } return $product_count; } /** * Get order counts * * @return array */ private static function get_order_counts() { $order_count = array(); $order_count_data = wp_count_posts( 'shop_order' ); foreach ( kkart_get_order_statuses() as $status_slug => $status_name ) { $order_count[ $status_slug ] = $order_count_data->{ $status_slug }; } return $order_count; } /** * Combine all order data. * * @return array */ private static function get_orders() { $order_dates = self::get_order_dates(); $order_counts = self::get_order_counts(); $order_totals = self::get_order_totals(); return array_merge( $order_dates, $order_counts, $order_totals ); } /** * Get review counts for different statuses. * * @return array */ private static function get_review_counts() { global $wpdb; $review_count = array( 'total' => 0 ); $status_map = array( '0' => 'pending', '1' => 'approved', 'trash' => 'trash', 'spam' => 'spam', ); $counts = $wpdb->get_results( " SELECT comment_approved, COUNT(*) AS num_reviews FROM {$wpdb->comments} WHERE comment_type = 'review' GROUP BY comment_approved ", ARRAY_A ); if ( ! $counts ) { return $review_count; } foreach ( $counts as $count ) { $status = $count['comment_approved']; if ( array_key_exists( $status, $status_map ) ) { $review_count[ $status_map[ $status ] ] = $count['num_reviews']; } $review_count['total'] += $count['num_reviews']; } return $review_count; } /** * Get the number of product categories. * * @return int */ private static function get_category_counts() { return wp_count_terms( 'product_cat' ); } /** * Get a list of all active payment gateways. * * @return array */ private static function get_active_payment_gateways() { $active_gateways = array(); $gateways = KKART()->payment_gateways->payment_gateways(); foreach ( $gateways as $id => $gateway ) { if ( isset( $gateway->enabled ) && 'yes' === $gateway->enabled ) { $active_gateways[ $id ] = array( 'title' => $gateway->title, 'supports' => $gateway->supports, ); } } return $active_gateways; } /** * Get a list of all active shipping methods. * * @return array */ private static function get_active_shipping_methods() { $active_methods = array(); $shipping_methods = KKART()->shipping()->get_shipping_methods(); foreach ( $shipping_methods as $id => $shipping_method ) { if ( isset( $shipping_method->enabled ) && 'yes' === $shipping_method->enabled ) { $active_methods[ $id ] = array( 'title' => $shipping_method->title, 'tax_status' => $shipping_method->tax_status, ); } } return $active_methods; } /** * Get all options starting with kkart_ prefix. * * @return array */ private static function get_all_kkart_options_values() { return array( 'version' => KKART()->version, 'currency' => get_kkart_currency(), 'base_location' => KKART()->countries->get_base_country(), 'selling_locations' => KKART()->countries->get_allowed_countries(), 'api_enabled' => get_option( 'kkart_api_enabled' ), 'weight_unit' => get_option( 'kkart_weight_unit' ), 'dimension_unit' => get_option( 'kkart_dimension_unit' ), 'download_method' => get_option( 'kkart_file_download_method' ), 'download_require_login' => get_option( 'kkart_downloads_require_login' ), 'calc_taxes' => get_option( 'kkart_calc_taxes' ), 'coupons_enabled' => get_option( 'kkart_enable_coupons' ), 'guest_checkout' => get_option( 'kkart_enable_guest_checkout' ), 'secure_checkout' => get_option( 'kkart_force_ssl_checkout' ), 'enable_signup_and_login_from_checkout' => get_option( 'kkart_enable_signup_and_login_from_checkout' ), 'enable_myaccount_registration' => get_option( 'kkart_enable_myaccount_registration' ), 'registration_generate_username' => get_option( 'kkart_registration_generate_username' ), 'registration_generate_password' => get_option( 'kkart_registration_generate_password' ), ); } /** * Look for any template override and return filenames. * * @return array */ private static function get_all_template_overrides() { $override_data = array(); $template_paths = apply_filters( 'kkart_template_overrides_scan_paths', array( 'Kkart' => KKART()->plugin_path() . '/templates/' ) ); $scanned_files = array(); require_once KKART()->plugin_path() . '/includes/admin/class-kkart-admin-status.php'; foreach ( $template_paths as $plugin_name => $template_path ) { $scanned_files[ $plugin_name ] = KKART_Admin_Status::scan_template_files( $template_path ); } foreach ( $scanned_files as $plugin_name => $files ) { foreach ( $files as $file ) { if ( file_exists( get_stylesheet_directory() . '/' . $file ) ) { $theme_file = get_stylesheet_directory() . '/' . $file; } elseif ( file_exists( get_stylesheet_directory() . '/' . KKART()->template_path() . $file ) ) { $theme_file = get_stylesheet_directory() . '/' . KKART()->template_path() . $file; } elseif ( file_exists( get_template_directory() . '/' . $file ) ) { $theme_file = get_template_directory() . '/' . $file; } elseif ( file_exists( get_template_directory() . '/' . KKART()->template_path() . $file ) ) { $theme_file = get_template_directory() . '/' . KKART()->template_path() . $file; } else { $theme_file = false; } if ( false !== $theme_file ) { $override_data[] = basename( $theme_file ); } } } return $override_data; } /** * When an admin user logs in, there user agent is tracked in user meta and collected here. * * @return array */ private static function get_admin_user_agents() { return array_filter( (array) get_option( 'kkart_tracker_ua', array() ) ); } /** * Get order totals * * @return array */ public static function get_order_totals() { global $wpdb; $gross_total = $wpdb->get_var( " SELECT SUM( order_meta.meta_value ) AS 'gross_total' FROM {$wpdb->prefix}posts AS orders LEFT JOIN {$wpdb->prefix}postmeta AS order_meta ON order_meta.post_id = orders.ID WHERE order_meta.meta_key = '_order_total' AND orders.post_status in ( 'kkart-completed', 'kkart-refunded' ) GROUP BY order_meta.meta_key " ); if ( is_null( $gross_total ) ) { $gross_total = 0; } $processing_gross_total = $wpdb->get_var( " SELECT SUM( order_meta.meta_value ) AS 'gross_total' FROM {$wpdb->prefix}posts AS orders LEFT JOIN {$wpdb->prefix}postmeta AS order_meta ON order_meta.post_id = orders.ID WHERE order_meta.meta_key = '_order_total' AND orders.post_status = 'kkart-processing' GROUP BY order_meta.meta_key " ); if ( is_null( $processing_gross_total ) ) { $processing_gross_total = 0; } return array( 'gross' => $gross_total, 'processing_gross' => $processing_gross_total, ); } /** * Get last order date * * @return string */ private static function get_order_dates() { global $wpdb; $min_max = $wpdb->get_row( " SELECT MIN( post_date_gmt ) as 'first', MAX( post_date_gmt ) as 'last' FROM {$wpdb->prefix}posts WHERE post_type = 'shop_order' AND post_status = 'kkart-completed' ", ARRAY_A ); if ( is_null( $min_max ) ) { $min_max = array( 'first' => '-', 'last' => '-', ); } $processing_min_max = $wpdb->get_row( " SELECT MIN( post_date_gmt ) as 'processing_first', MAX( post_date_gmt ) as 'processing_last' FROM {$wpdb->prefix}posts WHERE post_type = 'shop_order' AND post_status = 'kkart-processing' ", ARRAY_A ); if ( is_null( $processing_min_max ) ) { $processing_min_max = array( 'processing_first' => '-', 'processing_last' => '-', ); } return array_merge( $min_max, $processing_min_max ); } /** * Search a specific post for text content. * * @param integer $post_id The id of the post to search. * @param string $text The text to search for. * @return string 'Yes' if post contains $text (otherwise 'No'). */ public static function post_contains_text( $post_id, $text ) { global $wpdb; // Search for the text anywhere in the post. $wildcarded = "%{$text}%"; $result = $wpdb->get_var( $wpdb->prepare( " SELECT COUNT( * ) FROM {$wpdb->prefix}posts WHERE ID=%d AND {$wpdb->prefix}posts.post_content LIKE %s ", array( $post_id, $wildcarded ) ) ); return ( '0' !== $result ) ? 'Yes' : 'No'; } /** * Get blocks from a kkart page. * * @param string $woo_page_name A kkart page e.g. `checkout` or `cart`. * @return array Array of blocks as returned by parse_blocks(). */ private static function get_all_blocks_from_page( $woo_page_name ) { $page_id = kkart_get_page_id( $woo_page_name ); $page = get_post( $page_id ); if ( ! $page ) { return array(); } $blocks = parse_blocks( $page->post_content ); if ( ! $blocks ) { return array(); } return $blocks; } /** * Get all instances of the specified block on a specific woo page * (e.g. `cart` or `checkout` page). * * @param string $block_name The name (id) of a block, e.g. `kkart/cart`. * @param string $woo_page_name The woo page to search, e.g. `cart`. * @return array Array of blocks as returned by parse_blocks(). */ private static function get_blocks_from_page( $block_name, $woo_page_name ) { $page_blocks = self::get_all_blocks_from_page( $woo_page_name ); // Get any instances of the specified block. return array_values( array_filter( $page_blocks, function ( $block ) use ( $block_name ) { return ( $block_name === $block['blockName'] ); } ) ); } /** * Get tracker data for a specific block type on a kkart page. * * @param string $block_name The name (id) of a block, e.g. `kkart/cart`. * @param string $woo_page_name The woo page to search, e.g. `cart`. * @return array Associative array of tracker data with keys: * - page_contains_block * - block_attributes */ public static function get_block_tracker_data( $block_name, $woo_page_name ) { $blocks = self::get_blocks_from_page( $block_name, $woo_page_name ); $block_present = false; $attributes = array(); if ( $blocks && count( $blocks ) ) { // Return any customised attributes from the first block. $block_present = true; $attributes = $blocks[0]['attrs']; } return array( 'page_contains_block' => $block_present ? 'Yes' : 'No', 'block_attributes' => $attributes, ); } /** * Get info about the cart & checkout pages. * * @return array */ public static function get_cart_checkout_info() { $cart_page_id = kkart_get_page_id( 'cart' ); $checkout_page_id = kkart_get_page_id( 'checkout' ); $cart_block_data = self::get_block_tracker_data( 'kkart/cart', 'cart' ); $checkout_block_data = self::get_block_tracker_data( 'kkart/checkout', 'checkout' ); return array( 'cart_page_contains_cart_shortcode' => self::post_contains_text( $cart_page_id, '[kkart_cart]' ), 'checkout_page_contains_checkout_shortcode' => self::post_contains_text( $checkout_page_id, '[kkart_checkout]' ), 'cart_page_contains_cart_block' => $cart_block_data['page_contains_block'], 'cart_block_attributes' => $cart_block_data['block_attributes'], 'checkout_page_contains_checkout_block' => $checkout_block_data['page_contains_block'], 'checkout_block_attributes' => $checkout_block_data['block_attributes'], ); } } KKART_Tracker::init(); PK!pPϡ*tracks/class-kkart-tracks-footer-pixel.phpnu[add_event( $event ); return true; } /** * Add a Tracks event to the queue. * * @param KKART_Tracks_Event $event Event to track. */ public function add_event( $event ) { $this->events[] = $event; } /** * Add events as tracking pixels to page footer. */ public function render_tracking_pixels() { if ( empty( $this->events ) ) { return; } foreach ( $this->events as $event ) { $pixel = $event->build_pixel_url(); if ( ! $pixel ) { continue; } echo ''; } $this->events = array(); } /** * Fire off API calls for events that weren't converted to pixels. * * This handles wp_redirect(). */ public function send_tracks_requests() { if ( empty( $this->events ) ) { return; } foreach ( $this->events as $event ) { KKART_Tracks_Client::record_event( $event ); } } } PK!dЗtracks/class-kkart-tracks.phpnu[ home_url(), 'blog_lang' => get_user_locale( $user_id ), 'blog_id' => class_exists( 'Jetpack_Options' ) ? Jetpack_Options::get_option( 'id' ) : null, 'products_count' => self::get_products_count(), ); set_transient( 'kkart_tracks_blog_details', $blog_details, DAY_IN_SECONDS ); } return $blog_details; } /** * Gather details from the request to the server. * * @return array Server details. */ public static function get_server_details() { $data = array(); $data['_via_ua'] = isset( $_SERVER['HTTP_USER_AGENT'] ) ? kkart_clean( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : ''; $data['_via_ip'] = isset( $_SERVER['REMOTE_ADDR'] ) ? kkart_clean( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : ''; $data['_lg'] = isset( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ? kkart_clean( wp_unslash( $_SERVER['HTTP_ACCEPT_LANGUAGE'] ) ) : ''; $data['_dr'] = isset( $_SERVER['HTTP_REFERER'] ) ? kkart_clean( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : ''; $uri = isset( $_SERVER['REQUEST_URI'] ) ? kkart_clean( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; $host = isset( $_SERVER['HTTP_HOST'] ) ? kkart_clean( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : ''; $data['_dl'] = isset( $_SERVER['REQUEST_SCHEME'] ) ? kkart_clean( wp_unslash( $_SERVER['REQUEST_SCHEME'] ) ) . '://' . $host . $uri : ''; return $data; } /** * Record an event in Tracks - this is the preferred way to record events from PHP. * * @param string $event_name The name of the event. * @param array $properties Custom properties to send with the event. * @return bool|WP_Error True for success or WP_Error if the event pixel could not be fired. */ public static function record_event( $event_name, $properties = array() ) { /** * Don't track users who don't have tracking enabled. */ if ( ! KKART_Site_Tracking::is_tracking_enabled() ) { return false; } $user = wp_get_current_user(); // We don't want to track user events during unit tests/CI runs. if ( $user instanceof WP_User && 'wptests_capabilities' === $user->cap_key ) { return false; } $prefixed_event_name = self::PREFIX . $event_name; $data = array( '_en' => $prefixed_event_name, '_ts' => KKART_Tracks_Client::build_timestamp(), ); $server_details = self::get_server_details(); $identity = KKART_Tracks_Client::get_identity( $user->ID ); $blog_details = self::get_blog_details( $user->ID ); // Allow event props to be filtered to enable adding site-wide props. $filtered_properties = apply_filters( 'kkart_tracks_event_properties', $properties, $prefixed_event_name ); // Delete _ui and _ut protected properties. unset( $filtered_properties['_ui'] ); unset( $filtered_properties['_ut'] ); $event_obj = new KKART_Tracks_Event( array_merge( $data, $server_details, $identity, $blog_details, $filtered_properties ) ); if ( is_wp_error( $event_obj->error ) ) { return $event_obj->error; } return $event_obj->record(); } } PK! ?$tracks/class-kkart-tracks-client.phpnu[cap_key ) { return false; } $user_id = $user->ID; $anon_id = get_user_meta( $user_id, '_kkart_tracks_anon_id', true ); // If an id is still not found, create one and save it. if ( ! $anon_id ) { $anon_id = self::get_anon_id(); update_user_meta( $user_id, '_kkart_tracks_anon_id', $anon_id ); } // Don't set cookie on API requests. if ( ! Constants::is_true( 'REST_REQUEST' ) && ! Constants::is_true( 'XMLRPC_REQUEST' ) ) { kkart_setcookie( 'tk_ai', $anon_id ); } } /** * Record a Tracks event * * @param array $event Array of event properties. * @return bool|WP_Error True on success, WP_Error on failure. */ public static function record_event( $event ) { if ( ! $event instanceof KKART_Tracks_Event ) { $event = new KKART_Tracks_Event( $event ); } if ( is_wp_error( $event ) ) { return $event; } $pixel = $event->build_pixel_url( $event ); if ( ! $pixel ) { return new WP_Error( 'invalid_pixel', 'cannot generate tracks pixel for given input', 400 ); } return self::record_pixel( $pixel ); } /** * Synchronously request the pixel. * * @param string $pixel pixel url and query string. * @return bool Always returns true. */ public static function record_pixel( $pixel ) { // Add the Request Timestamp and URL terminator just before the HTTP request. $pixel .= '&_rt=' . self::build_timestamp() . '&_=_'; wp_safe_remote_get( $pixel, array( 'blocking' => false, 'redirection' => 2, 'httpversion' => '1.1', 'timeout' => 1, ) ); return true; } /** * Create a timestap representing milliseconds since 1970-01-01 * * @return string A string representing a timestamp. */ public static function build_timestamp() { $ts = NumberUtil::round( microtime( true ) * 1000 ); return number_format( $ts, 0, '', '' ); } /** * Get a user's identity to send to Tracks. If Jetpack exists, default to its implementation. * * @param int $user_id User id. * @return array Identity properties. */ public static function get_identity( $user_id ) { $jetpack_lib = '/tracks/client.php'; if ( class_exists( 'Jetpack' ) && Constants::is_defined( 'JETPACK__VERSION' ) ) { if ( version_compare( Constants::get_constant( 'JETPACK__VERSION' ), '7.5', '<' ) ) { if ( file_exists( jetpack_require_lib_dir() . $jetpack_lib ) ) { include_once jetpack_require_lib_dir() . $jetpack_lib; if ( function_exists( 'jetpack_tracks_get_identity' ) ) { return jetpack_tracks_get_identity( $user_id ); } } } else { $tracking = new Automattic\Jetpack\Tracking(); return $tracking->tracks_get_identity( $user_id ); } } // Start with a previously set cookie. $anon_id = isset( $_COOKIE['tk_ai'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['tk_ai'] ) ) : false; // If there is no cookie, apply a saved id. if ( ! $anon_id ) { $anon_id = get_user_meta( $user_id, '_kkart_tracks_anon_id', true ); } // If an id is still not found, create one and save it. if ( ! $anon_id ) { $anon_id = self::get_anon_id(); update_user_meta( $user_id, '_kkart_tracks_anon_id', $anon_id ); } return array( '_ut' => 'anon', '_ui' => $anon_id, ); } /** * Grabs the user's anon id from cookies, or generates and sets a new one * * @return string An anon id for the user */ public static function get_anon_id() { static $anon_id = null; if ( ! isset( $anon_id ) ) { // Did the browser send us a cookie? if ( isset( $_COOKIE['tk_ai'] ) ) { $anon_id = sanitize_text_field( wp_unslash( $_COOKIE['tk_ai'] ) ); } else { $binary = ''; // Generate a new anonId and try to save it in the browser's cookies. // Note that base64-encoding an 18 character string generates a 24-character anon id. for ( $i = 0; $i < 18; ++$i ) { $binary .= chr( wp_rand( 0, 255 ) ); } // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode $anon_id = 'woo:' . base64_encode( $binary ); } } return $anon_id; } } KKART_Tracks_Client::init(); PK!D)$tracks/class-kkart-site-tracking.phpnu[ registered['woo-tracks'] ) ) { return; } $woo_tracks_script = $wp_scripts->registered['woo-tracks']->src; ?> error = $_event; return; } foreach ( $_event as $key => $value ) { $this->{$key} = $value; } } /** * Record Tracks event * * @return bool Always returns true. */ public function record() { if ( wp_doing_ajax() || Constants::is_true( 'REST_REQUEST' ) ) { return KKART_Tracks_Client::record_event( $this ); } return KKART_Tracks_Footer_Pixel::record_event( $this ); } /** * Annotate the event with all relevant info. * * @param array $event Event arguments. * @return bool|WP_Error True on success, WP_Error on failure. */ public static function validate_and_sanitize( $event ) { $event = (object) $event; // Required. if ( ! $event->_en ) { return new WP_Error( 'invalid_event', 'A valid event must be specified via `_en`', 400 ); } // Delete non-routable addresses otherwise geoip will discard the record entirely. if ( property_exists( $event, '_via_ip' ) && preg_match( '/^192\.168|^10\./', $event->_via_ip ) ) { unset( $event->_via_ip ); } $validated = array( 'browser_type' => KKART_Tracks_Client::BROWSER_TYPE, ); $_event = (object) array_merge( (array) $event, $validated ); // If you want to block property names, do it here. // Make sure we have an event timestamp. if ( ! isset( $_event->_ts ) ) { $_event->_ts = KKART_Tracks_Client::build_timestamp(); } return $_event; } /** * Build a pixel URL that will send a Tracks event when fired. * On error, returns an empty string (''). * * @return string A pixel URL or empty string ('') if there were invalid args. */ public function build_pixel_url() { if ( $this->error ) { return ''; } $args = get_object_vars( $this ); // Request Timestamp and URL Terminator must be added just before the HTTP request or not at all. unset( $args['_rt'], $args['_'] ); $validated = self::validate_and_sanitize( $args ); if ( is_wp_error( $validated ) ) { return ''; } return esc_url_raw( KKART_Tracks_Client::PIXEL . '?' . http_build_query( $validated ) ); } /** * Check if event name is valid. * * @param string $name Event name. * @return false|int */ public static function event_name_is_valid( $name ) { return preg_match( self::EVENT_NAME_REGEX, $name ); } /** * Check if a property name is valid. * * @param string $name Event property. * @return false|int */ public static function prop_name_is_valid( $name ) { return preg_match( self::PROP_NAME_REGEX, $name ); } /** * Check event names * * @param object $event An event object. */ public static function scrutinize_event_names( $event ) { if ( ! self::event_name_is_valid( $event->_en ) ) { return; } $allowed_key_names = array( 'anonId', 'Browser_Type', ); foreach ( array_keys( (array) $event ) as $key ) { if ( in_array( $key, $allowed_key_names, true ) ) { continue; } if ( ! self::prop_name_is_valid( $key ) ) { return; } } } } PK!}}-tracks/events/class-kkart-orders-tracking.phpnu[id ) { // we are on the order listing page, and query results are being shown. KKART_Tracks::record_event( 'orders_view_search' ); } return $order_ids; } /** * Send a Tracks event when the Orders page is viewed. */ public function track_orders_view() { if ( isset( $_GET['post_type'] ) && 'shop_order' === wp_unslash( $_GET['post_type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized // phpcs:disable WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput $properties = array( 'status' => isset( $_GET['post_status'] ) ? sanitize_text_field( $_GET['post_status'] ) : 'all', ); // phpcs:enable KKART_Tracks::record_event( 'orders_view', $properties ); } } /** * Send a Tracks event when an order status is changed. * * @param int $id Order id. * @param string $previous_status the old Kkart order status. * @param string $next_status the new Kkart order status. */ public function track_order_status_change( $id, $previous_status, $next_status ) { $order = kkart_get_order( $id ); $properties = array( 'order_id' => $id, 'next_status' => $next_status, 'previous_status' => $previous_status, 'date_created' => $order->get_date_created() ? $order->get_date_created()->date( 'Y-m-d' ) : '', 'payment_method' => $order->get_payment_method(), 'order_total' => $order->get_total(), ); KKART_Tracks::record_event( 'orders_edit_status_change', $properties ); } /** * Send a Tracks event when an order date is changed. * * @param int $id Order id. */ public function track_created_date_change( $id ) { $post_type = get_post_type( $id ); if ( 'shop_order' !== $post_type ) { return; } if ( 'auto-draft' === get_post_status( $id ) ) { return; } $order = kkart_get_order( $id ); $date_created = $order->get_date_created() ? $order->get_date_created()->date( 'Y-m-d H:i:s' ) : ''; // phpcs:disable WordPress.Security.NonceVerification $new_date = sprintf( '%s %2d:%2d:%2d', isset( $_POST['order_date'] ) ? kkart_clean( wp_unslash( $_POST['order_date'] ) ) : '', isset( $_POST['order_date_hour'] ) ? kkart_clean( wp_unslash( $_POST['order_date_hour'] ) ) : '', isset( $_POST['order_date_minute'] ) ? kkart_clean( wp_unslash( $_POST['order_date_minute'] ) ) : '', isset( $_POST['order_date_second'] ) ? kkart_clean( wp_unslash( $_POST['order_date_second'] ) ) : '' ); // phpcs:enable if ( $new_date !== $date_created ) { $properties = array( 'order_id' => $id, 'status' => $order->get_status(), ); KKART_Tracks::record_event( 'order_edit_date_created', $properties ); } } /** * Track order actions taken. * * @param int $order_id Order ID. */ public function track_order_action( $order_id ) { // phpcs:disable WordPress.Security.NonceVerification if ( ! empty( $_POST['kkart_order_action'] ) ) { $order = kkart_get_order( $order_id ); $action = kkart_clean( wp_unslash( $_POST['kkart_order_action'] ) ); $properties = array( 'order_id' => $order_id, 'status' => $order->get_status(), 'action' => $action, ); KKART_Tracks::record_event( 'order_edit_order_action', $properties ); } // phpcs:enable } /** * Track "add order" button on the Edit Order screen. */ public function track_add_order_from_edit() { // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( isset( $_GET['post_type'] ) && 'shop_order' === wp_unslash( $_GET['post_type'] ) ) { $referer = wp_get_referer(); if ( $referer ) { $referring_page = wp_parse_url( $referer ); $referring_args = array(); $post_edit_page = wp_parse_url( admin_url( 'post.php' ) ); if ( ! empty( $referring_page['query'] ) ) { parse_str( $referring_page['query'], $referring_args ); } // Determine if we arrived from an Order Edit screen. if ( $post_edit_page['path'] === $referring_page['path'] && isset( $referring_args['action'] ) && 'edit' === $referring_args['action'] && isset( $referring_args['post'] ) && 'shop_order' === get_post_type( $referring_args['post'] ) ) { KKART_Tracks::record_event( 'order_edit_add_order' ); } } } } } PK!3\ /tracks/events/class-kkart-settings-tracking.phpnu[allowed_options[] = $option['id']; // Delay attaching this action since it could get fired a lot. if ( false === has_action( 'update_option', array( $this, 'track_setting_change' ) ) ) { add_action( 'update_option', array( $this, 'track_setting_change' ), 10, 3 ); } } /** * Add Kkart option to a list of updated options. * * @param string $option_name Option being updated. * @param mixed $old_value Old value of option. * @param mixed $new_value New value of option. */ public function track_setting_change( $option_name, $old_value, $new_value ) { // Make sure this is a Kkart option. if ( ! in_array( $option_name, $this->allowed_options, true ) ) { return; } // Check to make sure the new value is truly different. // `kkart_price_num_decimals` tends to trigger this // because form values aren't coerced (e.g. '2' vs. 2). if ( is_scalar( $old_value ) && is_scalar( $new_value ) && (string) $old_value === (string) $new_value ) { return; } $this->updated_options[] = $option_name; } /** * Send a Tracks event for Kkart options that changed values. */ public function send_settings_change_event() { global $current_tab; if ( empty( $this->updated_options ) ) { return; } $properties = array( 'settings' => implode( ',', $this->updated_options ), ); if ( isset( $current_tab ) ) { $properties['tab'] = $current_tab; } KKART_Tracks::record_event( 'settings_change', $properties ); } /** * Send a Tracks event for Kkart settings page views. */ public function track_settings_page_view() { global $current_tab, $current_section; $properties = array( 'tab' => $current_tab, 'section' => empty( $current_section ) ? null : $current_section, ); KKART_Tracks::record_event( 'settings_view', $properties ); } } PK!}},tracks/events/class-kkart-order-tracking.phpnu[get_id() ) { return; } $properties = array( 'current_status' => $order->get_status(), 'date_created' => $order->get_date_created() ? $order->get_date_created()->format( DateTime::ATOM ) : '', 'payment_method' => $order->get_payment_method(), ); KKART_Tracks::record_event( 'single_order_view', $properties ); } } PK!P~vv-tracks/events/class-kkart-coupon-tracking.phpnu[ $coupon->get_code(), 'free_shipping' => $coupon->get_free_shipping(), 'individual_use' => $coupon->get_individual_use(), 'exclude_sale_items' => $coupon->get_exclude_sale_items(), 'usage_limits_applied' => 0 < intval( $coupon->get_usage_limit() ) || 0 < intval( $coupon->get_usage_limit_per_user() ) || 0 < intval( $coupon->get_limit_usage_to_x_items() ), ); KKART_Tracks::record_event( 'coupon_updated', $properties ); } } PK!tBE  -tracks/events/class-kkart-status-tracking.phpnu[ $tab, 'tool_used' => isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : null, ) ); if ( 'status' === $tab ) { kkart_enqueue_js( " $( 'a.debug-report' ).click( function() { window.wcTracks.recordEvent( 'status_view_reports' ); } ); " ); } } } } PK! 1tracks/events/class-kkart-extensions-tracking.phpnu[ empty( $_REQUEST['section'] ) ? '_featured' : kkart_clean( wp_unslash( $_REQUEST['section'] ) ), ); if ( ! empty( $_REQUEST['search'] ) ) { $event = 'extensions_view_search'; $properties['search_term'] = kkart_clean( wp_unslash( $_REQUEST['search'] ) ); } // phpcs:enable KKART_Tracks::record_event( $event, $properties ); } /** * Send a Tracks even when a Helper connection process is initiated. */ public function track_helper_connection_start() { KKART_Tracks::record_event( 'extensions_subscriptions_connect' ); } /** * Send a Tracks even when a Helper connection process is cancelled. */ public function track_helper_connection_cancelled() { KKART_Tracks::record_event( 'extensions_subscriptions_cancelled' ); } /** * Send a Tracks even when a Helper connection process completed successfully. */ public function track_helper_connection_complete() { KKART_Tracks::record_event( 'extensions_subscriptions_connected' ); } /** * Send a Tracks even when a Helper has been disconnected. */ public function track_helper_disconnected() { KKART_Tracks::record_event( 'extensions_subscriptions_disconnect' ); } /** * Send a Tracks even when Helper subscriptions are refreshed. */ public function track_helper_subscriptions_refresh() { KKART_Tracks::record_event( 'extensions_subscriptions_update' ); } } PK!ZgLL9tracks/events/class-kkart-admin-setup-wizard-tracking.phpnu[queue as $script ) { if ( in_array( $script, $allowed, true ) ) { continue; } wp_dequeue_script( $script ); } } /** * Track when tracking is opted into and OBW has started. * * @param string $option Option name. * @param string $value Option value. * * @deprecated 4.6.0 */ public function track_start( $option, $value ) { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Track the marketing form on submit. * * @deprecated 4.6.0 */ public function track_ready_next_steps() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Track various events when a step is saved. * * @deprecated 4.6.0 */ public function add_step_save_events() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Track store setup and store properties on save. * * @deprecated 4.6.0 */ public function track_store_setup() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Track payment gateways selected. * * @deprecated 4.6.0 */ public function track_payments() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Track shipping units and whether or not labels are set. * * @deprecated 4.6.0 */ public function track_shipping() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Track recommended plugins selected for install. * * @deprecated 4.6.0 */ public function track_recommended() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Tracks when Jetpack is activated through the OBW. * * @deprecated 4.6.0 */ public function track_jetpack_activate() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Tracks when last next_steps screen is viewed in the OBW. * * @deprecated 4.6.0 */ public function track_next_steps() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Track skipped steps. * * @deprecated 4.6.0 */ public function track_skip_step() { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); } /** * Set the OBW steps inside this class instance. * * @param array $steps Array of OBW steps. * * @deprecated 4.6.0 */ public function set_obw_steps( $steps ) { _deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.6.0', __( 'Onboarding is maintained in Kkart Admin.', 'kkart' ) ); $this->steps = $steps; return $steps; } } PK!/tracks/events/class-kkart-importer-tracking.phpnu[track_product_importer_start(); } if ( 'done' === $_REQUEST['step'] ) { return $this->track_product_importer_complete(); } // phpcs:enable } /** * Send a Tracks event when the product importer is started. * * @return void */ public function track_product_importer_start() { // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! isset( $_REQUEST['file'] ) || ! isset( $_REQUEST['_wpnonce'] ) ) { return; } $properties = array( 'update_existing' => isset( $_REQUEST['update_existing'] ) ? (bool) $_REQUEST['update_existing'] : false, 'delimiter' => empty( $_REQUEST['delimiter'] ) ? ',' : kkart_clean( wp_unslash( $_REQUEST['delimiter'] ) ), ); // phpcs:enable KKART_Tracks::record_event( 'product_import_start', $properties ); } /** * Send a Tracks event when the product importer has finished. * * @return void */ public function track_product_importer_complete() { // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! isset( $_REQUEST['nonce'] ) ) { return; } $properties = array( 'imported' => isset( $_GET['products-imported'] ) ? absint( $_GET['products-imported'] ) : 0, 'updated' => isset( $_GET['products-updated'] ) ? absint( $_GET['products-updated'] ) : 0, 'failed' => isset( $_GET['products-failed'] ) ? absint( $_GET['products-failed'] ) : 0, 'skipped' => isset( $_GET['products-skipped'] ) ? absint( $_GET['products-skipped'] ) : 0, ); // phpcs:enable KKART_Tracks::record_event( 'product_import_complete', $properties ); } } PK!Vş77.tracks/events/class-kkart-coupons-tracking.phpnu[tracks_coupons_bulk_actions(); KKART_Tracks::record_event( 'coupons_view', array( 'status' => isset( $_GET['post_status'] ) ? sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) : 'all', ) ); if ( isset( $_GET['filter_action'] ) && 'Filter' === sanitize_text_field( wp_unslash( $_GET['filter_action'] ) ) && isset( $_GET['coupon_type'] ) ) { KKART_Tracks::record_event( 'coupons_filter', array( 'filter' => 'coupon_type', 'value' => sanitize_text_field( wp_unslash( $_GET['coupon_type'] ) ), ) ); } if ( isset( $_GET['s'] ) && 0 < strlen( sanitize_text_field( wp_unslash( $_GET['s'] ) ) ) ) { KKART_Tracks::record_event( 'coupons_search' ); } } } } PK!i/tracks/events/class-kkart-products-tracking.phpnu[post_type ) { return; } $properties = array( 'product_id' => $product_id, ); KKART_Tracks::record_event( 'product_edit', $properties ); } /** * Track the Update button being clicked on the client side. * This is needed because `track_product_updated` (using the `edit_post` * hook) is called in response to a number of other triggers. * * @param WP_Post $post The post, not used. */ public function track_product_updated_client_side( $post ) { kkart_enqueue_js( " if ( $( 'h1.wp-heading-inline' ).text().trim() === '" . __( 'Edit product', 'kkart' ) . "') { var initialStockValue = $( '#_stock' ).val(); var hasRecordedEvent = false; $( '#publish' ).click( function() { if ( hasRecordedEvent ) { return; } var currentStockValue = $( '#_stock' ).val(); var properties = { product_type: $( '#product-type' ).val(), is_virtual: $( '#_virtual' ).is( ':checked' ) ? 'Y' : 'N', is_downloadable: $( '#_downloadable' ).is( ':checked' ) ? 'Y' : 'N', manage_stock: $( '#_manage_stock' ).is( ':checked' ) ? 'Y' : 'N', stock_quantity_update: ( initialStockValue != currentStockValue ) ? 'Y' : 'N', }; window.wcTracks.recordEvent( 'product_update', properties ); hasRecordedEvent = true; } ); } " ); } /** * Send a Tracks event when a product is published. * * @param string $new_status New post_status. * @param string $old_status Previous post_status. * @param object $post WordPress post. */ public function track_product_published( $new_status, $old_status, $post ) { if ( 'product' !== $post->post_type || 'publish' !== $new_status || 'publish' === $old_status ) { return; } $properties = array( 'product_id' => $post->ID, ); KKART_Tracks::record_event( 'product_add_publish', $properties ); } /** * Send a Tracks event when a product category is created. * * @param int $category_id Category ID. */ public function track_product_category_created( $category_id ) { // phpcs:disable WordPress.Security.NonceVerification.Missing // Only track category creation from the edit product screen or the // category management screen (which both occur via AJAX). if ( ! Constants::is_defined( 'DOING_AJAX' ) || empty( $_POST['action'] ) || ( // Product Categories screen. 'add-tag' !== $_POST['action'] && // Edit Product screen. 'add-product_cat' !== $_POST['action'] ) ) { return; } $category = get_term( $category_id, 'product_cat' ); $properties = array( 'category_id' => $category_id, 'parent_id' => $category->parent, 'page' => ( 'add-tag' === $_POST['action'] ) ? 'categories' : 'product', ); // phpcs:enable KKART_Tracks::record_event( 'product_category_add', $properties ); } } PK!j 1emails/class-kkart-email-customer-new-account.phpnu[id = 'customer_new_account'; $this->customer_email = true; $this->title = __( 'New account', 'kkart' ); $this->description = __( 'Customer "new account" emails are sent to the customer when a customer signs up via checkout or account pages.', 'kkart' ); $this->template_html = 'emails/customer-new-account.php'; $this->template_plain = 'emails/plain/customer-new-account.php'; // Call parent constructor. parent::__construct(); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( 'Your {site_title} account has been created!', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'Welcome to {site_title}', 'kkart' ); } /** * Trigger. * * @param int $user_id User ID. * @param string $user_pass User password. * @param bool $password_generated Whether the password was generated automatically or not. */ public function trigger( $user_id, $user_pass = '', $password_generated = false ) { $this->setup_locale(); if ( $user_id ) { $this->object = new WP_User( $user_id ); $this->user_pass = $user_pass; $this->user_login = stripslashes( $this->object->user_login ); $this->user_email = stripslashes( $this->object->user_email ); $this->recipient = $this->user_email; $this->password_generated = $password_generated; } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'user_login' => $this->user_login, 'user_pass' => $this->user_pass, 'blogname' => $this->get_blogname(), 'password_generated' => $this->password_generated, 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'user_login' => $this->user_login, 'user_pass' => $this->user_pass, 'blogname' => $this->get_blogname(), 'password_generated' => $this->password_generated, 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'We look forward to seeing you soon.', 'kkart' ); } } endif; return new KKART_Email_Customer_New_Account(); PK!ά:3emails/class-kkart-email-customer-on-hold-order.phpnu[id = 'customer_on_hold_order'; $this->customer_email = true; $this->title = __( 'Order on-hold', 'kkart' ); $this->description = __( 'This is an order notification sent to customers containing order details after an order is placed on-hold.', 'kkart' ); $this->template_html = 'emails/customer-on-hold-order.php'; $this->template_plain = 'emails/plain/customer-on-hold-order.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Triggers for this email. add_action( 'kkart_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_cancelled_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 ); // Call parent constructor. parent::__construct(); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( 'Your {site_title} order has been received!', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'Thank you for your order', 'kkart' ); } /** * Trigger the sending of this email. * * @param int $order_id The order ID. * @param KKART_Order|false $order Order object. */ public function trigger( $order_id, $order = false ) { $this->setup_locale(); if ( $order_id && ! is_a( $order, 'KKART_Order' ) ) { $order = kkart_get_order( $order_id ); } if ( is_a( $order, 'KKART_Order' ) ) { $this->object = $order; $this->recipient = $this->object->get_billing_email(); $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'We look forward to fulfilling your order soon.', 'kkart' ); } } endif; return new KKART_Email_Customer_On_Hold_Order(); PK!g抽DD-emails/class-kkart-email-customer-invoice.phpnu[id = 'customer_invoice'; $this->customer_email = true; $this->title = __( 'Customer invoice / Order details', 'kkart' ); $this->description = __( 'Customer invoice emails can be sent to customers containing their order information and payment links.', 'kkart' ); $this->template_html = 'emails/customer-invoice.php'; $this->template_plain = 'emails/plain/customer-invoice.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Call parent constructor. parent::__construct(); $this->manual = true; } /** * Get email subject. * * @param bool $paid Whether the order has been paid or not. * @since 3.1.0 * @return string */ public function get_default_subject( $paid = false ) { if ( $paid ) { return __( 'Invoice for order #{order_number} on {site_title}', 'kkart' ); } else { return __( 'Your latest {site_title} invoice', 'kkart' ); } } /** * Get email heading. * * @param bool $paid Whether the order has been paid or not. * @since 3.1.0 * @return string */ public function get_default_heading( $paid = false ) { if ( $paid ) { return __( 'Invoice for order #{order_number}', 'kkart' ); } else { return __( 'Your invoice for order #{order_number}', 'kkart' ); } } /** * Get email subject. * * @return string */ public function get_subject() { if ( $this->object->has_status( array( 'completed', 'processing' ) ) ) { $subject = $this->get_option( 'subject_paid', $this->get_default_subject( true ) ); return apply_filters( 'kkart_email_subject_customer_invoice_paid', $this->format_string( $subject ), $this->object, $this ); } $subject = $this->get_option( 'subject', $this->get_default_subject() ); return apply_filters( 'kkart_email_subject_customer_invoice', $this->format_string( $subject ), $this->object, $this ); } /** * Get email heading. * * @return string */ public function get_heading() { if ( $this->object->has_status( kkart_get_is_paid_statuses() ) ) { $heading = $this->get_option( 'heading_paid', $this->get_default_heading( true ) ); return apply_filters( 'kkart_email_heading_customer_invoice_paid', $this->format_string( $heading ), $this->object, $this ); } $heading = $this->get_option( 'heading', $this->get_default_heading() ); return apply_filters( 'kkart_email_heading_customer_invoice', $this->format_string( $heading ), $this->object, $this ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Thanks for using {site_url}!', 'kkart' ); } /** * Trigger the sending of this email. * * @param int $order_id The order ID. * @param KKART_Order $order Order object. */ public function trigger( $order_id, $order = false ) { $this->setup_locale(); if ( $order_id && ! is_a( $order, 'KKART_Order' ) ) { $order = kkart_get_order( $order_id ); } if ( is_a( $order, 'KKART_Order' ) ) { $this->object = $order; $this->recipient = $this->object->get_billing_email(); $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } if ( $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Initialise settings form fields. */ public function init_form_fields() { /* translators: %s: list of placeholders */ $placeholder_text = sprintf( __( 'Available placeholders: %s', 'kkart' ), '' . esc_html( implode( ', ', array_keys( $this->placeholders ) ) ) . '' ); $this->form_fields = array( 'subject' => array( 'title' => __( 'Subject', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject(), 'default' => '', ), 'heading' => array( 'title' => __( 'Email heading', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading(), 'default' => '', ), 'subject_paid' => array( 'title' => __( 'Subject (paid)', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject( true ), 'default' => '', ), 'heading_paid' => array( 'title' => __( 'Email heading (paid)', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading( true ), 'default' => '', ), 'additional_content' => array( 'title' => __( 'Additional content', 'kkart' ), 'description' => __( 'Text to appear below the main email content.', 'kkart' ) . ' ' . $placeholder_text, 'css' => 'width:400px; height: 75px;', 'placeholder' => __( 'N/A', 'kkart' ), 'type' => 'textarea', 'default' => $this->get_default_additional_content(), 'desc_tip' => true, ), 'email_type' => array( 'title' => __( 'Email type', 'kkart' ), 'type' => 'select', 'description' => __( 'Choose which format of email to send.', 'kkart' ), 'default' => 'html', 'class' => 'email_type kkart-enhanced-select', 'options' => $this->get_email_type_options(), 'desc_tip' => true, ), ); } } endif; return new KKART_Email_Customer_Invoice(); PK!k)*emails/class-kkart-email-customer-note.phpnu[id = 'customer_note'; $this->customer_email = true; $this->title = __( 'Customer note', 'kkart' ); $this->description = __( 'Customer note emails are sent when you add a note to an order.', 'kkart' ); $this->template_html = 'emails/customer-note.php'; $this->template_plain = 'emails/plain/customer-note.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Triggers. add_action( 'kkart_new_customer_note_notification', array( $this, 'trigger' ) ); // Call parent constructor. parent::__construct(); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( 'Note added to your {site_title} order from {order_date}', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'A note has been added to your order', 'kkart' ); } /** * Trigger. * * @param array $args Email arguments. */ public function trigger( $args ) { $this->setup_locale(); if ( ! empty( $args ) ) { $defaults = array( 'order_id' => '', 'customer_note' => '', ); $args = wp_parse_args( $args, $defaults ); $order_id = $args['order_id']; $customer_note = $args['customer_note']; if ( $order_id ) { $this->object = kkart_get_order( $order_id ); if ( $this->object ) { $this->recipient = $this->object->get_billing_email(); $this->customer_note = $customer_note; $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } } } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'customer_note' => $this->customer_note, 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'customer_note' => $this->customer_note, 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Thanks for reading.', 'kkart' ); } } endif; return new KKART_Email_Customer_Note(); PK!xbS5emails/class-kkart-email-customer-completed-order.phpnu[id = 'customer_completed_order'; $this->customer_email = true; $this->title = __( 'Completed order', 'kkart' ); $this->description = __( 'Order complete emails are sent to customers when their orders are marked completed and usually indicate that their orders have been shipped.', 'kkart' ); $this->template_html = 'emails/customer-completed-order.php'; $this->template_plain = 'emails/plain/customer-completed-order.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Triggers for this email. add_action( 'kkart_order_status_completed_notification', array( $this, 'trigger' ), 10, 2 ); // Call parent constructor. parent::__construct(); } /** * Trigger the sending of this email. * * @param int $order_id The order ID. * @param KKART_Order|false $order Order object. */ public function trigger( $order_id, $order = false ) { $this->setup_locale(); if ( $order_id && ! is_a( $order, 'KKART_Order' ) ) { $order = kkart_get_order( $order_id ); } if ( is_a( $order, 'KKART_Order' ) ) { $this->object = $order; $this->recipient = $this->object->get_billing_email(); $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( 'Your {site_title} order is now complete', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'Thanks for shopping with us', 'kkart' ); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Thanks for shopping with us.', 'kkart' ); } } endif; return new KKART_Email_Customer_Completed_Order(); PK!Y4emails/class-kkart-email-customer-reset-password.phpnu[id = 'customer_reset_password'; $this->customer_email = true; $this->title = __( 'Reset password', 'kkart' ); $this->description = __( 'Customer "reset password" emails are sent when customers reset their passwords.', 'kkart' ); $this->template_html = 'emails/customer-reset-password.php'; $this->template_plain = 'emails/plain/customer-reset-password.php'; // Trigger. add_action( 'kkart_reset_password_notification', array( $this, 'trigger' ), 10, 2 ); // Call parent constructor. parent::__construct(); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( 'Password Reset Request for {site_title}', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'Password Reset Request', 'kkart' ); } /** * Trigger. * * @param string $user_login User login. * @param string $reset_key Password reset key. */ public function trigger( $user_login = '', $reset_key = '' ) { $this->setup_locale(); if ( $user_login && $reset_key ) { $this->object = get_user_by( 'login', $user_login ); $this->user_id = $this->object->ID; $this->user_login = $user_login; $this->reset_key = $reset_key; $this->user_email = stripslashes( $this->object->user_email ); $this->recipient = $this->user_email; } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'email_heading' => $this->get_heading(), 'user_id' => $this->user_id, 'user_login' => $this->user_login, 'reset_key' => $this->reset_key, 'blogname' => $this->get_blogname(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'email_heading' => $this->get_heading(), 'user_id' => $this->user_id, 'user_login' => $this->user_login, 'reset_key' => $this->reset_key, 'blogname' => $this->get_blogname(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Thanks for reading.', 'kkart' ); } } endif; return new KKART_Email_Customer_Reset_Password(); PK!-qemails/class-kkart-email.phpnu[', // Greater-than. '<', // Less-than. '&', // Ampersand. '&', // Ampersand. '(c)', // Copyright. '(tm)', // Trademark. '(R)', // Registered. '--', // mdash. '-', // ndash. '*', // Bullet. '£', // Pound sign. 'EUR', // Euro sign. € ?. '$', // Dollar sign. '', // Unknown/unhandled entities. ' ', // Runs of spaces, post-handling. ); /** * Strings to find/replace in subjects/headings. * * @var array */ protected $placeholders = array(); /** * Strings to find in subjects/headings. * * @deprecated 3.2.0 in favour of placeholders * @var array */ public $find = array(); /** * Strings to replace in subjects/headings. * * @deprecated 3.2.0 in favour of placeholders * @var array */ public $replace = array(); /** * Constructor. */ public function __construct() { // Find/replace. $this->placeholders = array_merge( array( '{site_title}' => $this->get_blogname(), '{site_address}' => wp_parse_url( home_url(), PHP_URL_HOST ), '{site_url}' => wp_parse_url( home_url(), PHP_URL_HOST ), ), $this->placeholders ); // Init settings. $this->init_form_fields(); $this->init_settings(); // Default template base if not declared in child constructor. if ( is_null( $this->template_base ) ) { $this->template_base = KKART()->plugin_path() . '/templates/'; } $this->email_type = $this->get_option( 'email_type' ); $this->enabled = $this->get_option( 'enabled' ); add_action( 'phpmailer_init', array( $this, 'handle_multipart' ) ); add_action( 'kkart_update_options_email_' . $this->id, array( $this, 'process_admin_options' ) ); } /** * Handle multipart mail. * * @param PHPMailer $mailer PHPMailer object. * @return PHPMailer */ public function handle_multipart( $mailer ) { if ( $this->sending && 'multipart' === $this->get_email_type() ) { $mailer->AltBody = wordwrap( // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase preg_replace( $this->plain_search, $this->plain_replace, wp_strip_all_tags( $this->get_content_plain() ) ) ); $this->sending = false; } return $mailer; } /** * Format email string. * * @param mixed $string Text to replace placeholders in. * @return string */ public function format_string( $string ) { $find = array_keys( $this->placeholders ); $replace = array_values( $this->placeholders ); // If using legacy find replace, add those to our find/replace arrays first. @todo deprecate in 4.0.0. $find = array_merge( (array) $this->find, $find ); $replace = array_merge( (array) $this->replace, $replace ); // Take care of blogname which is no longer defined as a valid placeholder. $find[] = '{blogname}'; $replace[] = $this->get_blogname(); // If using the older style filters for find and replace, ensure the array is associative and then pass through filters. @todo deprecate in 4.0.0. if ( has_filter( 'kkart_email_format_string_replace' ) || has_filter( 'kkart_email_format_string_find' ) ) { $legacy_find = $this->find; $legacy_replace = $this->replace; foreach ( $this->placeholders as $find => $replace ) { $legacy_key = sanitize_title( str_replace( '_', '-', trim( $find, '{}' ) ) ); $legacy_find[ $legacy_key ] = $find; $legacy_replace[ $legacy_key ] = $replace; } $string = str_replace( apply_filters( 'kkart_email_format_string_find', $legacy_find, $this ), apply_filters( 'kkart_email_format_string_replace', $legacy_replace, $this ), $string ); } /** * Filter for main find/replace. * * @since 3.2.0 */ return apply_filters( 'kkart_email_format_string', str_replace( $find, $replace, $string ), $this ); } /** * Set the locale to the store locale for customer emails to make sure emails are in the store language. */ public function setup_locale() { if ( $this->is_customer_email() && apply_filters( 'kkart_email_setup_locale', true ) ) { kkart_switch_to_site_locale(); } } /** * Restore the locale to the default locale. Use after finished with setup_locale. */ public function restore_locale() { if ( $this->is_customer_email() && apply_filters( 'kkart_email_restore_locale', true ) ) { kkart_restore_locale(); } } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return $this->subject; } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return $this->heading; } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return ''; } /** * Return content from the additional_content field. * * Displayed above the footer. * * @since 3.7.0 * @return string */ public function get_additional_content() { $content = $this->get_option( 'additional_content', '' ); return apply_filters( 'kkart_email_additional_content_' . $this->id, $this->format_string( $content ), $this->object, $this ); } /** * Get email subject. * * @return string */ public function get_subject() { return apply_filters( 'kkart_email_subject_' . $this->id, $this->format_string( $this->get_option( 'subject', $this->get_default_subject() ) ), $this->object, $this ); } /** * Get email heading. * * @return string */ public function get_heading() { return apply_filters( 'kkart_email_heading_' . $this->id, $this->format_string( $this->get_option( 'heading', $this->get_default_heading() ) ), $this->object, $this ); } /** * Get valid recipients. * * @return string */ public function get_recipient() { $recipient = apply_filters( 'kkart_email_recipient_' . $this->id, $this->recipient, $this->object, $this ); $recipients = array_map( 'trim', explode( ',', $recipient ) ); $recipients = array_filter( $recipients, 'is_email' ); return implode( ', ', $recipients ); } /** * Get email headers. * * @return string */ public function get_headers() { $header = 'Content-Type: ' . $this->get_content_type() . "\r\n"; if ( in_array( $this->id, array( 'new_order', 'cancelled_order', 'failed_order' ), true ) ) { if ( $this->object && $this->object->get_billing_email() && ( $this->object->get_billing_first_name() || $this->object->get_billing_last_name() ) ) { $header .= 'Reply-to: ' . $this->object->get_billing_first_name() . ' ' . $this->object->get_billing_last_name() . ' <' . $this->object->get_billing_email() . ">\r\n"; } } elseif ( $this->get_from_address() && $this->get_from_name() ) { $header .= 'Reply-to: ' . $this->get_from_name() . ' <' . $this->get_from_address() . ">\r\n"; } return apply_filters( 'kkart_email_headers', $header, $this->id, $this->object, $this ); } /** * Get email attachments. * * @return array */ public function get_attachments() { return apply_filters( 'kkart_email_attachments', array(), $this->id, $this->object, $this ); } /** * Return email type. * * @return string */ public function get_email_type() { return $this->email_type && class_exists( 'DOMDocument' ) ? $this->email_type : 'plain'; } /** * Get email content type. * * @param string $default_content_type Default wp_mail() content type. * @return string */ public function get_content_type( $default_content_type = '' ) { switch ( $this->get_email_type() ) { case 'html': $content_type = 'text/html'; break; case 'multipart': $content_type = 'multipart/alternative'; break; default: $content_type = 'text/plain'; break; } return apply_filters( 'kkart_email_content_type', $content_type, $this, $default_content_type ); } /** * Return the email's title * * @return string */ public function get_title() { return apply_filters( 'kkart_email_title', $this->title, $this ); } /** * Return the email's description * * @return string */ public function get_description() { return apply_filters( 'kkart_email_description', $this->description, $this ); } /** * Proxy to parent's get_option and attempt to localize the result using gettext. * * @param string $key Option key. * @param mixed $empty_value Value to use when option is empty. * @return string */ public function get_option( $key, $empty_value = null ) { $value = parent::get_option( $key, $empty_value ); return apply_filters( 'kkart_email_get_option', $value, $this, $value, $key, $empty_value ); } /** * Checks if this email is enabled and will be sent. * * @return bool */ public function is_enabled() { return apply_filters( 'kkart_email_enabled_' . $this->id, 'yes' === $this->enabled, $this->object, $this ); } /** * Checks if this email is manually sent * * @return bool */ public function is_manual() { return $this->manual; } /** * Checks if this email is customer focussed. * * @return bool */ public function is_customer_email() { return $this->customer_email; } /** * Get WordPress blog name. * * @return string */ public function get_blogname() { return wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ); } /** * Get email content. * * @return string */ public function get_content() { $this->sending = true; if ( 'plain' === $this->get_email_type() ) { $email_content = wordwrap( preg_replace( $this->plain_search, $this->plain_replace, wp_strip_all_tags( $this->get_content_plain() ) ), 70 ); } else { $email_content = $this->get_content_html(); } return $email_content; } /** * Apply inline styles to dynamic content. * * We only inline CSS for html emails, and to do so we use Emogrifier library (if supported). * * @version 4.0.0 * @param string|null $content Content that will receive inline styles. * @return string */ public function style_inline( $content ) { if ( in_array( $this->get_content_type(), array( 'text/html', 'multipart/alternative' ), true ) ) { ob_start(); kkart_get_template( 'emails/email-styles.php' ); $css = apply_filters( 'kkart_email_styles', ob_get_clean(), $this ); $emogrifier_class = 'Pelago\\Emogrifier'; if ( $this->supports_emogrifier() && class_exists( $emogrifier_class ) ) { try { $emogrifier = new $emogrifier_class( $content, $css ); do_action( 'kkart_emogrifier', $emogrifier, $this ); $content = $emogrifier->emogrify(); $html_prune = \Pelago\Emogrifier\HtmlProcessor\HtmlPruner::fromHtml( $content ); $html_prune->removeElementsWithDisplayNone(); $content = $html_prune->render(); } catch ( Exception $e ) { $logger = kkart_get_logger(); $logger->error( $e->getMessage(), array( 'source' => 'emogrifier' ) ); } } else { $content = '' . $content; } } return $content; } /** * Return if emogrifier library is supported. * * @version 4.0.0 * @since 3.5.0 * @return bool */ protected function supports_emogrifier() { return class_exists( 'DOMDocument' ); } /** * Get the email content in plain text format. * * @return string */ public function get_content_plain() { return ''; } /** * Get the email content in HTML format. * * @return string */ public function get_content_html() { return ''; } /** * Get the from name for outgoing emails. * * @param string $from_name Default wp_mail() name associated with the "from" email address. * @return string */ public function get_from_name( $from_name = '' ) { $from_name = apply_filters( 'kkart_email_from_name', get_option( 'kkart_email_from_name' ), $this, $from_name ); return wp_specialchars_decode( esc_html( $from_name ), ENT_QUOTES ); } /** * Get the from address for outgoing emails. * * @param string $from_email Default wp_mail() email address to send from. * @return string */ public function get_from_address( $from_email = '' ) { $from_email = apply_filters( 'kkart_email_from_address', get_option( 'kkart_email_from_address' ), $this, $from_email ); return sanitize_email( $from_email ); } /** * Send an email. * * @param string $to Email to. * @param string $subject Email subject. * @param string $message Email message. * @param string $headers Email headers. * @param array $attachments Email attachments. * @return bool success */ public function send( $to, $subject, $message, $headers, $attachments ) { add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); $message = apply_filters( 'kkart_mail_content', $this->style_inline( $message ) ); $mail_callback = apply_filters( 'kkart_mail_callback', 'wp_mail', $this ); $mail_callback_params = apply_filters( 'kkart_mail_callback_params', array( $to, $subject, $message, $headers, $attachments ), $this ); $return = $mail_callback( ...$mail_callback_params ); remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); return $return; } /** * Initialise Settings Form Fields - these are generic email options most will use. */ public function init_form_fields() { /* translators: %s: list of placeholders */ $placeholder_text = sprintf( __( 'Available placeholders: %s', 'kkart' ), '' . esc_html( implode( ', ', array_keys( $this->placeholders ) ) ) . '' ); $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Enable this email notification', 'kkart' ), 'default' => 'yes', ), 'subject' => array( 'title' => __( 'Subject', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject(), 'default' => '', ), 'heading' => array( 'title' => __( 'Email heading', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading(), 'default' => '', ), 'additional_content' => array( 'title' => __( 'Additional content', 'kkart' ), 'description' => __( 'Text to appear below the main email content.', 'kkart' ) . ' ' . $placeholder_text, 'css' => 'width:400px; height: 75px;', 'placeholder' => __( 'N/A', 'kkart' ), 'type' => 'textarea', 'default' => $this->get_default_additional_content(), 'desc_tip' => true, ), 'email_type' => array( 'title' => __( 'Email type', 'kkart' ), 'type' => 'select', 'description' => __( 'Choose which format of email to send.', 'kkart' ), 'default' => 'html', 'class' => 'email_type kkart-enhanced-select', 'options' => $this->get_email_type_options(), 'desc_tip' => true, ), ); } /** * Email type options. * * @return array */ public function get_email_type_options() { $types = array( 'plain' => __( 'Plain text', 'kkart' ) ); if ( class_exists( 'DOMDocument' ) ) { $types['html'] = __( 'HTML', 'kkart' ); $types['multipart'] = __( 'Multipart', 'kkart' ); } return $types; } /** * Admin Panel Options Processing. */ public function process_admin_options() { // Save regular options. parent::process_admin_options(); $post_data = $this->get_post_data(); // Save templates. if ( isset( $post_data['template_html_code'] ) ) { $this->save_template( $post_data['template_html_code'], $this->template_html ); } if ( isset( $post_data['template_plain_code'] ) ) { $this->save_template( $post_data['template_plain_code'], $this->template_plain ); } } /** * Get template. * * @param string $type Template type. Can be either 'template_html' or 'template_plain'. * @return string */ public function get_template( $type ) { $type = basename( $type ); if ( 'template_html' === $type ) { return $this->template_html; } elseif ( 'template_plain' === $type ) { return $this->template_plain; } return ''; } /** * Save the email templates. * * @since 2.4.0 * @param string $template_code Template code. * @param string $template_path Template path. */ protected function save_template( $template_code, $template_path ) { if ( current_user_can( 'edit_themes' ) && ! empty( $template_code ) && ! empty( $template_path ) ) { $saved = false; $file = get_stylesheet_directory() . '/' . KKART()->template_path() . $template_path; $code = wp_unslash( $template_code ); if ( is_writeable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writeable $f = fopen( $file, 'w+' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fopen if ( false !== $f ) { fwrite( $f, $code ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fwrite fclose( $f ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_fclose $saved = true; } } if ( ! $saved ) { $redirect = add_query_arg( 'kkart_error', rawurlencode( __( 'Could not write to template file.', 'kkart' ) ) ); wp_safe_redirect( $redirect ); exit; } } } /** * Get the template file in the current theme. * * @param string $template Template name. * * @return string */ public function get_theme_template_file( $template ) { return get_stylesheet_directory() . '/' . apply_filters( 'kkart_template_directory', 'kkart', $template ) . '/' . $template; } /** * Move template action. * * @param string $template_type Template type. */ protected function move_template_action( $template_type ) { $template = $this->get_template( $template_type ); if ( ! empty( $template ) ) { $theme_file = $this->get_theme_template_file( $template ); if ( wp_mkdir_p( dirname( $theme_file ) ) && ! file_exists( $theme_file ) ) { // Locate template file. $core_file = $this->template_base . $template; $template_file = apply_filters( 'kkart_locate_core_template', $core_file, $template, $this->template_base, $this->id ); // Copy template file. copy( $template_file, $theme_file ); /** * Action hook fired after copying email template file. * * @param string $template_type The copied template type * @param string $email The email object */ do_action( 'kkart_copy_email_template', $template_type, $this ); ?>

get_template( $template_type ); if ( $template ) { if ( ! empty( $template ) ) { $theme_file = $this->get_theme_template_file( $template ); if ( file_exists( $theme_file ) ) { unlink( $theme_file ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink /** * Action hook fired after deleting template file. * * @param string $template The deleted template type * @param string $email The email object */ do_action( 'kkart_delete_email_template', $template_type, $this ); ?>

template_html ) || ! empty( $this->template_plain ) ) && ( ! empty( $_GET['move_template'] ) || ! empty( $_GET['delete_template'] ) ) && 'GET' === $_SERVER['REQUEST_METHOD'] // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated ) { if ( empty( $_GET['_kkart_email_nonce'] ) || ! wp_verify_nonce( kkart_clean( wp_unslash( $_GET['_kkart_email_nonce'] ) ), 'kkart_email_template_nonce' ) ) { wp_die( esc_html__( 'Action failed. Please refresh the page and retry.', 'kkart' ) ); } if ( ! current_user_can( 'edit_themes' ) ) { wp_die( esc_html__( 'You don’t have permission to do this.', 'kkart' ) ); } if ( ! empty( $_GET['move_template'] ) ) { $this->move_template_action( kkart_clean( wp_unslash( $_GET['move_template'] ) ) ); } if ( ! empty( $_GET['delete_template'] ) ) { $this->delete_template_action( kkart_clean( wp_unslash( $_GET['delete_template'] ) ) ); } } } /** * Admin Options. * * Setup the email settings screen. * Override this in your email. * * @since 1.0.0 */ public function admin_options() { // Do admin actions. $this->admin_actions(); ?>

get_title() ); ?>

get_description() ) ); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped ?> generate_settings_html(); ?>
template_html ) || ! empty( $this->template_plain ) ) ) { ?>
__( 'HTML template', 'kkart' ), 'template_plain' => __( 'Plain text template', 'kkart' ), ); foreach ( $templates as $template_type => $title ) : $template = $this->get_template( $template_type ); if ( empty( $template ) ) { continue; } $local_file = $this->get_theme_template_file( $template ); $core_file = $this->template_base . $template; $template_file = apply_filters( 'kkart_locate_core_template', $core_file, $template, $this->template_base, $this->id ); $template_dir = apply_filters( 'kkart_template_directory', 'kkart', $template ); ?>

' . esc_html( trailingslashit( basename( get_stylesheet_directory() ) ) . $template_dir . '/' . $template ) . '' ); ?>

' . esc_html( plugin_basename( $template_file ) ) . '', '' . esc_html( trailingslashit( basename( get_stylesheet_directory() ) ) . $template_dir . '/' . $template ) . '' ); ?>

id = 'cancelled_order'; $this->title = __( 'Cancelled order', 'kkart' ); $this->description = __( 'Cancelled order emails are sent to chosen recipient(s) when orders have been marked cancelled (if they were previously processing or on-hold).', 'kkart' ); $this->template_html = 'emails/admin-cancelled-order.php'; $this->template_plain = 'emails/plain/admin-cancelled-order.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', '{order_billing_full_name}' => '', ); // Triggers for this email. add_action( 'kkart_order_status_processing_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_on-hold_to_cancelled_notification', array( $this, 'trigger' ), 10, 2 ); // Call parent constructor. parent::__construct(); // Other settings. $this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) ); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( '[{site_title}]: Order #{order_number} has been cancelled', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'Order Cancelled: #{order_number}', 'kkart' ); } /** * Trigger the sending of this email. * * @param int $order_id The order ID. * @param KKART_Order|false $order Order object. */ public function trigger( $order_id, $order = false ) { $this->setup_locale(); if ( $order_id && ! is_a( $order, 'KKART_Order' ) ) { $order = kkart_get_order( $order_id ); } if ( is_a( $order, 'KKART_Order' ) ) { $this->object = $order; $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); $this->placeholders['{order_billing_full_name}'] = $this->object->get_formatted_billing_full_name(); } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => true, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => true, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Thanks for reading.', 'kkart' ); } /** * Initialise settings form fields. */ public function init_form_fields() { /* translators: %s: list of placeholders */ $placeholder_text = sprintf( __( 'Available placeholders: %s', 'kkart' ), '' . esc_html( implode( ', ', array_keys( $this->placeholders ) ) ) . '' ); $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Enable this email notification', 'kkart' ), 'default' => 'yes', ), 'recipient' => array( 'title' => __( 'Recipient(s)', 'kkart' ), 'type' => 'text', /* translators: %s: admin email */ 'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'kkart' ), '' . esc_attr( get_option( 'admin_email' ) ) . '' ), 'placeholder' => '', 'default' => '', 'desc_tip' => true, ), 'subject' => array( 'title' => __( 'Subject', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject(), 'default' => '', ), 'heading' => array( 'title' => __( 'Email heading', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading(), 'default' => '', ), 'additional_content' => array( 'title' => __( 'Additional content', 'kkart' ), 'description' => __( 'Text to appear below the main email content.', 'kkart' ) . ' ' . $placeholder_text, 'css' => 'width:400px; height: 75px;', 'placeholder' => __( 'N/A', 'kkart' ), 'type' => 'textarea', 'default' => $this->get_default_additional_content(), 'desc_tip' => true, ), 'email_type' => array( 'title' => __( 'Email type', 'kkart' ), 'type' => 'select', 'description' => __( 'Choose which format of email to send.', 'kkart' ), 'default' => 'html', 'class' => 'email_type kkart-enhanced-select', 'options' => $this->get_email_type_options(), 'desc_tip' => true, ), ); } } endif; return new KKART_Email_Cancelled_Order(); PK!)emails/class-kkart-email-failed-order.phpnu[id = 'failed_order'; $this->title = __( 'Failed order', 'kkart' ); $this->description = __( 'Failed order emails are sent to chosen recipient(s) when orders have been marked failed (if they were previously pending or on-hold).', 'kkart' ); $this->template_html = 'emails/admin-failed-order.php'; $this->template_plain = 'emails/plain/admin-failed-order.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Triggers for this email. add_action( 'kkart_order_status_pending_to_failed_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_on-hold_to_failed_notification', array( $this, 'trigger' ), 10, 2 ); // Call parent constructor. parent::__construct(); // Other settings. $this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) ); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( '[{site_title}]: Order #{order_number} has failed', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'Order Failed: #{order_number}', 'kkart' ); } /** * Trigger the sending of this email. * * @param int $order_id The order ID. * @param KKART_Order|false $order Order object. */ public function trigger( $order_id, $order = false ) { $this->setup_locale(); if ( $order_id && ! is_a( $order, 'KKART_Order' ) ) { $order = kkart_get_order( $order_id ); } if ( is_a( $order, 'KKART_Order' ) ) { $this->object = $order; $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => true, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => true, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Hopefully they’ll be back. Read more about troubleshooting failed payments.', 'kkart' ); } /** * Initialise settings form fields. */ public function init_form_fields() { /* translators: %s: list of placeholders */ $placeholder_text = sprintf( __( 'Available placeholders: %s', 'kkart' ), '' . esc_html( implode( ', ', array_keys( $this->placeholders ) ) ) . '' ); $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Enable this email notification', 'kkart' ), 'default' => 'yes', ), 'recipient' => array( 'title' => __( 'Recipient(s)', 'kkart' ), 'type' => 'text', /* translators: %s: WP admin email */ 'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'kkart' ), '' . esc_attr( get_option( 'admin_email' ) ) . '' ), 'placeholder' => '', 'default' => '', 'desc_tip' => true, ), 'subject' => array( 'title' => __( 'Subject', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject(), 'default' => '', ), 'heading' => array( 'title' => __( 'Email heading', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading(), 'default' => '', ), 'additional_content' => array( 'title' => __( 'Additional content', 'kkart' ), 'description' => __( 'Text to appear below the main email content.', 'kkart' ) . ' ' . $placeholder_text, 'css' => 'width:400px; height: 75px;', 'placeholder' => __( 'N/A', 'kkart' ), 'type' => 'textarea', 'default' => $this->get_default_additional_content(), 'desc_tip' => true, ), 'email_type' => array( 'title' => __( 'Email type', 'kkart' ), 'type' => 'select', 'description' => __( 'Choose which format of email to send.', 'kkart' ), 'default' => 'html', 'class' => 'email_type kkart-enhanced-select', 'options' => $this->get_email_type_options(), 'desc_tip' => true, ), ); } } endif; return new KKART_Email_Failed_Order(); PK!P nn6emails/class-kkart-email-customer-processing-order.phpnu[id = 'customer_processing_order'; $this->customer_email = true; $this->title = __( 'Processing order', 'kkart' ); $this->description = __( 'This is an order notification sent to customers containing order details after payment.', 'kkart' ); $this->template_html = 'emails/customer-processing-order.php'; $this->template_plain = 'emails/plain/customer-processing-order.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Triggers for this email. add_action( 'kkart_order_status_cancelled_to_processing_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_on-hold_to_processing_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 ); // Call parent constructor. parent::__construct(); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( 'Your {site_title} order has been received!', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'Thank you for your order', 'kkart' ); } /** * Trigger the sending of this email. * * @param int $order_id The order ID. * @param KKART_Order|false $order Order object. */ public function trigger( $order_id, $order = false ) { $this->setup_locale(); if ( $order_id && ! is_a( $order, 'KKART_Order' ) ) { $order = kkart_get_order( $order_id ); } if ( is_a( $order, 'KKART_Order' ) ) { $this->object = $order; $this->recipient = $this->object->get_billing_email(); $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Thanks for using {site_url}!', 'kkart' ); } } endif; return new KKART_Email_Customer_Processing_Order(); PK!Te&emails/class-kkart-email-new-order.phpnu[id = 'new_order'; $this->title = __( 'New order', 'kkart' ); $this->description = __( 'New order emails are sent to chosen recipient(s) when a new order is received.', 'kkart' ); $this->template_html = 'emails/admin-new-order.php'; $this->template_plain = 'emails/plain/admin-new-order.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Triggers for this email. add_action( 'kkart_order_status_pending_to_processing_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_pending_to_completed_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_pending_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_failed_to_processing_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_failed_to_completed_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_failed_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_cancelled_to_processing_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_cancelled_to_completed_notification', array( $this, 'trigger' ), 10, 2 ); add_action( 'kkart_order_status_cancelled_to_on-hold_notification', array( $this, 'trigger' ), 10, 2 ); // Call parent constructor. parent::__construct(); // Other settings. $this->recipient = $this->get_option( 'recipient', get_option( 'admin_email' ) ); } /** * Get email subject. * * @since 3.1.0 * @return string */ public function get_default_subject() { return __( '[{site_title}]: New order #{order_number}', 'kkart' ); } /** * Get email heading. * * @since 3.1.0 * @return string */ public function get_default_heading() { return __( 'New Order: #{order_number}', 'kkart' ); } /** * Trigger the sending of this email. * * @param int $order_id The order ID. * @param KKART_Order|false $order Order object. */ public function trigger( $order_id, $order = false ) { $this->setup_locale(); if ( $order_id && ! is_a( $order, 'KKART_Order' ) ) { $order = kkart_get_order( $order_id ); } if ( is_a( $order, 'KKART_Order' ) ) { $this->object = $order; $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => true, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => true, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'Congratulations on the sale.', 'kkart' ); } /** * Initialise settings form fields. */ public function init_form_fields() { /* translators: %s: list of placeholders */ $placeholder_text = sprintf( __( 'Available placeholders: %s', 'kkart' ), '' . implode( ', ', array_keys( $this->placeholders ) ) . '' ); $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Enable this email notification', 'kkart' ), 'default' => 'yes', ), 'recipient' => array( 'title' => __( 'Recipient(s)', 'kkart' ), 'type' => 'text', /* translators: %s: WP admin email */ 'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to %s.', 'kkart' ), '' . esc_attr( get_option( 'admin_email' ) ) . '' ), 'placeholder' => '', 'default' => '', 'desc_tip' => true, ), 'subject' => array( 'title' => __( 'Subject', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject(), 'default' => '', ), 'heading' => array( 'title' => __( 'Email heading', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading(), 'default' => '', ), 'additional_content' => array( 'title' => __( 'Additional content', 'kkart' ), 'description' => __( 'Text to appear below the main email content.', 'kkart' ) . ' ' . $placeholder_text, 'css' => 'width:400px; height: 75px;', 'placeholder' => __( 'N/A', 'kkart' ), 'type' => 'textarea', 'default' => $this->get_default_additional_content(), 'desc_tip' => true, ), 'email_type' => array( 'title' => __( 'Email type', 'kkart' ), 'type' => 'select', 'description' => __( 'Choose which format of email to send.', 'kkart' ), 'default' => 'html', 'class' => 'email_type kkart-enhanced-select', 'options' => $this->get_email_type_options(), 'desc_tip' => true, ), ); } } endif; return new KKART_Email_New_Order(); PK!=)~##4emails/class-kkart-email-customer-refunded-order.phpnu[customer_email = true; $this->id = 'customer_refunded_order'; $this->title = __( 'Refunded order', 'kkart' ); $this->description = __( 'Order refunded emails are sent to customers when their orders are refunded.', 'kkart' ); $this->template_html = 'emails/customer-refunded-order.php'; $this->template_plain = 'emails/plain/customer-refunded-order.php'; $this->placeholders = array( '{order_date}' => '', '{order_number}' => '', ); // Triggers for this email. add_action( 'kkart_order_fully_refunded_notification', array( $this, 'trigger_full' ), 10, 2 ); add_action( 'kkart_order_partially_refunded_notification', array( $this, 'trigger_partial' ), 10, 2 ); // Call parent constructor. parent::__construct(); } /** * Get email subject. * * @param bool $partial Whether it is a partial refund or a full refund. * @since 3.1.0 * @return string */ public function get_default_subject( $partial = false ) { if ( $partial ) { return __( 'Your {site_title} order #{order_number} has been partially refunded', 'kkart' ); } else { return __( 'Your {site_title} order #{order_number} has been refunded', 'kkart' ); } } /** * Get email heading. * * @param bool $partial Whether it is a partial refund or a full refund. * @since 3.1.0 * @return string */ public function get_default_heading( $partial = false ) { if ( $partial ) { return __( 'Partial Refund: Order {order_number}', 'kkart' ); } else { return __( 'Order Refunded: {order_number}', 'kkart' ); } } /** * Get email subject. * * @return string */ public function get_subject() { if ( $this->partial_refund ) { $subject = $this->get_option( 'subject_partial', $this->get_default_subject( true ) ); } else { $subject = $this->get_option( 'subject_full', $this->get_default_subject() ); } return apply_filters( 'kkart_email_subject_customer_refunded_order', $this->format_string( $subject ), $this->object, $this ); } /** * Get email heading. * * @return string */ public function get_heading() { if ( $this->partial_refund ) { $heading = $this->get_option( 'heading_partial', $this->get_default_heading( true ) ); } else { $heading = $this->get_option( 'heading_full', $this->get_default_heading() ); } return apply_filters( 'kkart_email_heading_customer_refunded_order', $this->format_string( $heading ), $this->object, $this ); } /** * Set email strings. * * @param bool $partial_refund Whether it is a partial refund or a full refund. * @deprecated 3.1.0 Unused. */ public function set_email_strings( $partial_refund = false ) {} /** * Full refund notification. * * @param int $order_id Order ID. * @param int $refund_id Refund ID. */ public function trigger_full( $order_id, $refund_id = null ) { $this->trigger( $order_id, false, $refund_id ); } /** * Partial refund notification. * * @param int $order_id Order ID. * @param int $refund_id Refund ID. */ public function trigger_partial( $order_id, $refund_id = null ) { $this->trigger( $order_id, true, $refund_id ); } /** * Trigger. * * @param int $order_id Order ID. * @param bool $partial_refund Whether it is a partial refund or a full refund. * @param int $refund_id Refund ID. */ public function trigger( $order_id, $partial_refund = false, $refund_id = null ) { $this->setup_locale(); $this->partial_refund = $partial_refund; $this->id = $this->partial_refund ? 'customer_partially_refunded_order' : 'customer_refunded_order'; if ( $order_id ) { $this->object = kkart_get_order( $order_id ); $this->recipient = $this->object->get_billing_email(); $this->placeholders['{order_date}'] = kkart_format_datetime( $this->object->get_date_created() ); $this->placeholders['{order_number}'] = $this->object->get_order_number(); } if ( ! empty( $refund_id ) ) { $this->refund = kkart_get_order( $refund_id ); } else { $this->refund = false; } if ( $this->is_enabled() && $this->get_recipient() ) { $this->send( $this->get_recipient(), $this->get_subject(), $this->get_content(), $this->get_headers(), $this->get_attachments() ); } $this->restore_locale(); } /** * Get content html. * * @return string */ public function get_content_html() { return kkart_get_template_html( $this->template_html, array( 'order' => $this->object, 'refund' => $this->refund, 'partial_refund' => $this->partial_refund, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => false, 'email' => $this, ) ); } /** * Get content plain. * * @return string */ public function get_content_plain() { return kkart_get_template_html( $this->template_plain, array( 'order' => $this->object, 'refund' => $this->refund, 'partial_refund' => $this->partial_refund, 'email_heading' => $this->get_heading(), 'additional_content' => $this->get_additional_content(), 'sent_to_admin' => false, 'plain_text' => true, 'email' => $this, ) ); } /** * Default content to show below main email content. * * @since 3.7.0 * @return string */ public function get_default_additional_content() { return __( 'We hope to see you again soon.', 'kkart' ); } /** * Initialise settings form fields. */ public function init_form_fields() { /* translators: %s: list of placeholders */ $placeholder_text = sprintf( __( 'Available placeholders: %s', 'kkart' ), '' . esc_html( implode( ', ', array_keys( $this->placeholders ) ) ) . '' ); $this->form_fields = array( 'enabled' => array( 'title' => __( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => __( 'Enable this email notification', 'kkart' ), 'default' => 'yes', ), 'subject_full' => array( 'title' => __( 'Full refund subject', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject(), 'default' => '', ), 'subject_partial' => array( 'title' => __( 'Partial refund subject', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_subject( true ), 'default' => '', ), 'heading_full' => array( 'title' => __( 'Full refund email heading', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading(), 'default' => '', ), 'heading_partial' => array( 'title' => __( 'Partial refund email heading', 'kkart' ), 'type' => 'text', 'desc_tip' => true, 'description' => $placeholder_text, 'placeholder' => $this->get_default_heading( true ), 'default' => '', ), 'additional_content' => array( 'title' => __( 'Additional content', 'kkart' ), 'description' => __( 'Text to appear below the main email content.', 'kkart' ) . ' ' . $placeholder_text, 'css' => 'width:400px; height: 75px;', 'placeholder' => __( 'N/A', 'kkart' ), 'type' => 'textarea', 'default' => $this->get_default_additional_content(), 'desc_tip' => true, ), 'email_type' => array( 'title' => __( 'Email type', 'kkart' ), 'type' => 'select', 'description' => __( 'Choose which format of email to send.', 'kkart' ), 'default' => 'html', 'class' => 'email_type kkart-enhanced-select', 'options' => $this->get_email_type_options(), 'desc_tip' => true, ), ); } } endif; return new KKART_Email_Customer_Refunded_Order(); PK!22kkart-account-functions.phpnu[ 0; $lost_password_endpoint = get_option( 'kkart_myaccount_lost_password_endpoint' ); if ( $kkart_account_page_exists && ! empty( $lost_password_endpoint ) ) { return kkart_get_endpoint_url( $lost_password_endpoint, '', $kkart_account_page_url ); } else { return $default_url; } } add_filter( 'lostpassword_url', 'kkart_lostpassword_url', 10, 1 ); /** * Get the link to the edit account details page. * * @return string */ function kkart_customer_edit_account_url() { $edit_account_url = kkart_get_endpoint_url( 'edit-account', '', kkart_get_page_permalink( 'myaccount' ) ); return apply_filters( 'kkart_customer_edit_account_url', $edit_account_url ); } /** * Get the edit address slug translation. * * @param string $id Address ID. * @param bool $flip Flip the array to make it possible to retrieve the values ​​from both sides. * * @return string Address slug i18n. */ function kkart_edit_address_i18n( $id, $flip = false ) { $slugs = apply_filters( 'kkart_edit_address_slugs', array( 'billing' => sanitize_title( _x( 'billing', 'edit-address-slug', 'kkart' ) ), 'shipping' => sanitize_title( _x( 'shipping', 'edit-address-slug', 'kkart' ) ), ) ); if ( $flip ) { $slugs = array_flip( $slugs ); } if ( ! isset( $slugs[ $id ] ) ) { return $id; } return $slugs[ $id ]; } /** * Get My Account menu items. * * @since 2.6.0 * @return array */ function kkart_get_account_menu_items() { $endpoints = array( 'orders' => get_option( 'kkart_myaccount_orders_endpoint', 'orders' ), 'downloads' => get_option( 'kkart_myaccount_downloads_endpoint', 'downloads' ), 'edit-address' => get_option( 'kkart_myaccount_edit_address_endpoint', 'edit-address' ), 'payment-methods' => get_option( 'kkart_myaccount_payment_methods_endpoint', 'payment-methods' ), 'edit-account' => get_option( 'kkart_myaccount_edit_account_endpoint', 'edit-account' ), 'customer-logout' => get_option( 'kkart_logout_endpoint', 'customer-logout' ), ); $items = array( 'dashboard' => __( 'Dashboard', 'kkart' ), 'orders' => __( 'Orders', 'kkart' ), 'downloads' => __( 'Downloads', 'kkart' ), 'edit-address' => _n( 'Addresses', 'Address', (int) kkart_shipping_enabled(), 'kkart' ), 'payment-methods' => __( 'Payment methods', 'kkart' ), 'edit-account' => __( 'Account details', 'kkart' ), 'customer-logout' => __( 'Logout', 'kkart' ), ); // Remove missing endpoints. foreach ( $endpoints as $endpoint_id => $endpoint ) { if ( empty( $endpoint ) ) { unset( $items[ $endpoint_id ] ); } } // Check if payment gateways support add new payment methods. if ( isset( $items['payment-methods'] ) ) { $support_payment_methods = false; foreach ( KKART()->payment_gateways->get_available_payment_gateways() as $gateway ) { if ( $gateway->supports( 'add_payment_method' ) || $gateway->supports( 'tokenization' ) ) { $support_payment_methods = true; break; } } if ( ! $support_payment_methods ) { unset( $items['payment-methods'] ); } } return apply_filters( 'kkart_account_menu_items', $items, $endpoints ); } /** * Get account menu item classes. * * @since 2.6.0 * @param string $endpoint Endpoint. * @return string */ function kkart_get_account_menu_item_classes( $endpoint ) { global $wp; $classes = array( 'kkart-MyAccount-navigation-link', 'kkart-MyAccount-navigation-link--' . $endpoint, ); // Set current item class. $current = isset( $wp->query_vars[ $endpoint ] ); if ( 'dashboard' === $endpoint && ( isset( $wp->query_vars['page'] ) || empty( $wp->query_vars ) ) ) { $current = true; // Dashboard is not an endpoint, so needs a custom check. } elseif ( 'orders' === $endpoint && isset( $wp->query_vars['view-order'] ) ) { $current = true; // When looking at individual order, highlight Orders list item (to signify where in the menu the user currently is). } elseif ( 'payment-methods' === $endpoint && isset( $wp->query_vars['add-payment-method'] ) ) { $current = true; } if ( $current ) { $classes[] = 'is-active'; } $classes = apply_filters( 'kkart_account_menu_item_classes', $classes, $endpoint ); return implode( ' ', array_map( 'sanitize_html_class', $classes ) ); } /** * Get account endpoint URL. * * @since 2.6.0 * @param string $endpoint Endpoint. * @return string */ function kkart_get_account_endpoint_url( $endpoint ) { if ( 'dashboard' === $endpoint ) { return kkart_get_page_permalink( 'myaccount' ); } if ( 'customer-logout' === $endpoint ) { return kkart_logout_url(); } return kkart_get_endpoint_url( $endpoint, '', kkart_get_page_permalink( 'myaccount' ) ); } /** * Get My Account > Orders columns. * * @since 2.6.0 * @return array */ function kkart_get_account_orders_columns() { $columns = apply_filters( 'kkart_account_orders_columns', array( 'order-number' => __( 'Order', 'kkart' ), 'order-date' => __( 'Date', 'kkart' ), 'order-status' => __( 'Status', 'kkart' ), 'order-total' => __( 'Total', 'kkart' ), 'order-actions' => __( 'Actions', 'kkart' ), ) ); // Deprecated filter since 2.6.0. return apply_filters( 'kkart_my_account_my_orders_columns', $columns ); } /** * Get My Account > Downloads columns. * * @since 2.6.0 * @return array */ function kkart_get_account_downloads_columns() { $columns = apply_filters( 'kkart_account_downloads_columns', array( 'download-product' => __( 'Product', 'kkart' ), 'download-remaining' => __( 'Downloads remaining', 'kkart' ), 'download-expires' => __( 'Expires', 'kkart' ), 'download-file' => __( 'Download', 'kkart' ), 'download-actions' => ' ', ) ); if ( ! has_filter( 'kkart_account_download_actions' ) ) { unset( $columns['download-actions'] ); } return $columns; } /** * Get My Account > Payment methods columns. * * @since 2.6.0 * @return array */ function kkart_get_account_payment_methods_columns() { return apply_filters( 'kkart_account_payment_methods_columns', array( 'method' => __( 'Method', 'kkart' ), 'expires' => __( 'Expires', 'kkart' ), 'actions' => ' ', ) ); } /** * Get My Account > Payment methods types * * @since 2.6.0 * @return array */ function kkart_get_account_payment_methods_types() { return apply_filters( 'kkart_payment_methods_types', array( 'cc' => __( 'Credit card', 'kkart' ), 'echeck' => __( 'eCheck', 'kkart' ), ) ); } /** * Get account orders actions. * * @since 3.2.0 * @param int|KKART_Order $order Order instance or ID. * @return array */ function kkart_get_account_orders_actions( $order ) { if ( ! is_object( $order ) ) { $order_id = absint( $order ); $order = kkart_get_order( $order_id ); } $actions = array( 'pay' => array( 'url' => $order->get_checkout_payment_url(), 'name' => __( 'Pay', 'kkart' ), ), 'view' => array( 'url' => $order->get_view_order_url(), 'name' => __( 'View', 'kkart' ), ), 'cancel' => array( 'url' => $order->get_cancel_order_url( kkart_get_page_permalink( 'myaccount' ) ), 'name' => __( 'Cancel', 'kkart' ), ), ); if ( ! $order->needs_payment() ) { unset( $actions['pay'] ); } if ( ! in_array( $order->get_status(), apply_filters( 'kkart_valid_order_statuses_for_cancel', array( 'pending', 'failed' ), $order ), true ) ) { unset( $actions['cancel'] ); } return apply_filters( 'kkart_my_account_my_orders_actions', $actions, $order ); } /** * Get account formatted address. * * @since 3.2.0 * @param string $address_type Address type. * Accepts: 'billing' or 'shipping'. * Default to 'billing'. * @param int $customer_id Customer ID. * Default to 0. * @return string */ function kkart_get_account_formatted_address( $address_type = 'billing', $customer_id = 0 ) { $getter = "get_{$address_type}"; $address = array(); if ( 0 === $customer_id ) { $customer_id = get_current_user_id(); } $customer = new KKART_Customer( $customer_id ); if ( is_callable( array( $customer, $getter ) ) ) { $address = $customer->$getter(); unset( $address['email'], $address['tel'] ); } return KKART()->countries->get_formatted_address( apply_filters( 'kkart_my_account_my_address_formatted_address', $address, $customer->get_id(), $address_type ) ); } /** * Returns an array of a user's saved payments list for output on the account tab. * * @since 2.6 * @param array $list List of payment methods passed from kkart_get_customer_saved_methods_list(). * @param int $customer_id The customer to fetch payment methods for. * @return array Filtered list of customers payment methods. */ function kkart_get_account_saved_payment_methods_list( $list, $customer_id ) { $payment_tokens = KKART_Payment_Tokens::get_customer_tokens( $customer_id ); foreach ( $payment_tokens as $payment_token ) { $delete_url = kkart_get_endpoint_url( 'delete-payment-method', $payment_token->get_id() ); $delete_url = wp_nonce_url( $delete_url, 'delete-payment-method-' . $payment_token->get_id() ); $set_default_url = kkart_get_endpoint_url( 'set-default-payment-method', $payment_token->get_id() ); $set_default_url = wp_nonce_url( $set_default_url, 'set-default-payment-method-' . $payment_token->get_id() ); $type = strtolower( $payment_token->get_type() ); $list[ $type ][] = array( 'method' => array( 'gateway' => $payment_token->get_gateway_id(), ), 'expires' => esc_html__( 'N/A', 'kkart' ), 'is_default' => $payment_token->is_default(), 'actions' => array( 'delete' => array( 'url' => $delete_url, 'name' => esc_html__( 'Delete', 'kkart' ), ), ), ); $key = key( array_slice( $list[ $type ], -1, 1, true ) ); if ( ! $payment_token->is_default() ) { $list[ $type ][ $key ]['actions']['default'] = array( 'url' => $set_default_url, 'name' => esc_html__( 'Make default', 'kkart' ), ); } $list[ $type ][ $key ] = apply_filters( 'kkart_payment_methods_list_item', $list[ $type ][ $key ], $payment_token ); } return $list; } add_filter( 'kkart_saved_payment_methods_list', 'kkart_get_account_saved_payment_methods_list', 10, 2 ); /** * Controls the output for credit cards on the my account page. * * @since 2.6 * @param array $item Individual list item from kkart_saved_payment_methods_list. * @param KKART_Payment_Token $payment_token The payment token associated with this method entry. * @return array Filtered item. */ function kkart_get_account_saved_payment_methods_list_item_cc( $item, $payment_token ) { if ( 'cc' !== strtolower( $payment_token->get_type() ) ) { return $item; } $card_type = $payment_token->get_card_type(); $item['method']['last4'] = $payment_token->get_last4(); $item['method']['brand'] = ( ! empty( $card_type ) ? ucfirst( $card_type ) : esc_html__( 'Credit card', 'kkart' ) ); $item['expires'] = $payment_token->get_expiry_month() . '/' . substr( $payment_token->get_expiry_year(), -2 ); return $item; } add_filter( 'kkart_payment_methods_list_item', 'kkart_get_account_saved_payment_methods_list_item_cc', 10, 2 ); /** * Controls the output for eChecks on the my account page. * * @since 2.6 * @param array $item Individual list item from kkart_saved_payment_methods_list. * @param KKART_Payment_Token $payment_token The payment token associated with this method entry. * @return array Filtered item. */ function kkart_get_account_saved_payment_methods_list_item_echeck( $item, $payment_token ) { if ( 'echeck' !== strtolower( $payment_token->get_type() ) ) { return $item; } $item['method']['last4'] = $payment_token->get_last4(); $item['method']['brand'] = esc_html__( 'eCheck', 'kkart' ); return $item; } add_filter( 'kkart_payment_methods_list_item', 'kkart_get_account_saved_payment_methods_list_item_echeck', 10, 2 ); PK!ΰ|*|*kkart-rest-functions.phpnu[setTimezone( new DateTimeZone( kkart_timezone_string() ) ); } elseif ( is_string( $date ) ) { $date = new KKART_DateTime( $date, new DateTimeZone( 'UTC' ) ); $date->setTimezone( new DateTimeZone( kkart_timezone_string() ) ); } if ( ! is_a( $date, 'KKART_DateTime' ) ) { return null; } // Get timestamp before changing timezone to UTC. return gmdate( 'Y-m-d\TH:i:s', $utc ? $date->getTimestamp() : $date->getOffsetTimestamp() ); } /** * Returns image mime types users are allowed to upload via the API. * * @since 2.6.4 * @return array */ function kkart_rest_allowed_image_mime_types() { return apply_filters( 'kkart_rest_allowed_image_mime_types', array( 'jpg|jpeg|jpe' => 'image/jpeg', 'gif' => 'image/gif', 'png' => 'image/png', 'bmp' => 'image/bmp', 'tiff|tif' => 'image/tiff', 'ico' => 'image/x-icon', ) ); } /** * Upload image from URL. * * @since 2.6.0 * @param string $image_url Image URL. * @return array|WP_Error Attachment data or error message. */ function kkart_rest_upload_image_from_url( $image_url ) { $parsed_url = wp_parse_url( $image_url ); // Check parsed URL. if ( ! $parsed_url || ! is_array( $parsed_url ) ) { /* translators: %s: image URL */ return new WP_Error( 'kkart_rest_invalid_image_url', sprintf( __( 'Invalid URL %s.', 'kkart' ), $image_url ), array( 'status' => 400 ) ); } // Ensure url is valid. $image_url = esc_url_raw( $image_url ); // download_url function is part of wp-admin. if ( ! function_exists( 'download_url' ) ) { include_once KKART_ADMIN_DIR . 'includes/file.php'; } $file_array = array(); $file_array['name'] = basename( current( explode( '?', $image_url ) ) ); // Download file to temp location. $file_array['tmp_name'] = download_url( $image_url ); // If error storing temporarily, return the error. if ( is_wp_error( $file_array['tmp_name'] ) ) { return new WP_Error( 'kkart_rest_invalid_remote_image_url', /* translators: %s: image URL */ sprintf( __( 'Error getting remote image %s.', 'kkart' ), $image_url ) . ' ' /* translators: %s: error message */ . sprintf( __( 'Error: %s', 'kkart' ), $file_array['tmp_name']->get_error_message() ), array( 'status' => 400 ) ); } // Do the validation and storage stuff. $file = wp_handle_sideload( $file_array, array( 'test_form' => false, 'mimes' => kkart_rest_allowed_image_mime_types(), ), current_time( 'Y/m' ) ); if ( isset( $file['error'] ) ) { @unlink( $file_array['tmp_name'] ); // @codingStandardsIgnoreLine. /* translators: %s: error message */ return new WP_Error( 'kkart_rest_invalid_image', sprintf( __( 'Invalid image: %s', 'kkart' ), $file['error'] ), array( 'status' => 400 ) ); } do_action( 'kkart_rest_api_uploaded_image_from_url', $file, $image_url ); return $file; } /** * Set uploaded image as attachment. * * @since 2.6.0 * @param array $upload Upload information from wp_upload_bits. * @param int $id Post ID. Default to 0. * @return int Attachment ID */ function kkart_rest_set_uploaded_image_as_attachment( $upload, $id = 0 ) { $info = wp_check_filetype( $upload['file'] ); $title = ''; $content = ''; if ( ! function_exists( 'wp_generate_attachment_metadata' ) ) { include_once KKART_ADMIN_DIR . 'includes/image.php'; } $image_meta = wp_read_image_metadata( $upload['file'] ); if ( $image_meta ) { if ( trim( $image_meta['title'] ) && ! is_numeric( sanitize_title( $image_meta['title'] ) ) ) { $title = kkart_clean( $image_meta['title'] ); } if ( trim( $image_meta['caption'] ) ) { $content = kkart_clean( $image_meta['caption'] ); } } $attachment = array( 'post_mime_type' => $info['type'], 'guid' => $upload['url'], 'post_parent' => $id, 'post_title' => $title ? $title : basename( $upload['file'] ), 'post_content' => $content, ); $attachment_id = wp_insert_attachment( $attachment, $upload['file'], $id ); if ( ! is_wp_error( $attachment_id ) ) { wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $upload['file'] ) ); } return $attachment_id; } /** * Validate reports request arguments. * * @since 2.6.0 * @param mixed $value Value to valdate. * @param WP_REST_Request $request Request instance. * @param string $param Param to validate. * @return WP_Error|boolean */ function kkart_rest_validate_reports_request_arg( $value, $request, $param ) { $attributes = $request->get_attributes(); if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { return true; } $args = $attributes['args'][ $param ]; if ( 'string' === $args['type'] && ! is_string( $value ) ) { /* translators: 1: param 2: type */ return new WP_Error( 'kkart_rest_invalid_param', sprintf( __( '%1$s is not of type %2$s', 'kkart' ), $param, 'string' ) ); } if ( 'date' === $args['format'] ) { $regex = '#^\d{4}-\d{2}-\d{2}$#'; if ( ! preg_match( $regex, $value, $matches ) ) { return new WP_Error( 'kkart_rest_invalid_date', __( 'The date you provided is invalid.', 'kkart' ) ); } } return true; } /** * Encodes a value according to RFC 3986. * Supports multidimensional arrays. * * @since 2.6.0 * @param string|array $value The value to encode. * @return string|array Encoded values. */ function kkart_rest_urlencode_rfc3986( $value ) { if ( is_array( $value ) ) { return array_map( 'kkart_rest_urlencode_rfc3986', $value ); } return str_replace( array( '+', '%7E' ), array( ' ', '~' ), rawurlencode( $value ) ); } /** * Check permissions of posts on REST API. * * @since 2.6.0 * @param string $post_type Post type. * @param string $context Request context. * @param int $object_id Post ID. * @return bool */ function kkart_rest_check_post_permissions( $post_type, $context = 'read', $object_id = 0 ) { $contexts = array( 'read' => 'read_private_posts', 'create' => 'publish_posts', 'edit' => 'edit_post', 'delete' => 'delete_post', 'batch' => 'edit_others_posts', ); if ( 'revision' === $post_type ) { $permission = false; } else { $cap = $contexts[ $context ]; $post_type_object = get_post_type_object( $post_type ); $permission = current_user_can( $post_type_object->cap->$cap, $object_id ); } return apply_filters( 'kkart_rest_check_permissions', $permission, $context, $object_id, $post_type ); } /** * Check permissions of users on REST API. * * @since 2.6.0 * @param string $context Request context. * @param int $object_id Post ID. * @return bool */ function kkart_rest_check_user_permissions( $context = 'read', $object_id = 0 ) { $contexts = array( 'read' => 'list_users', 'create' => 'promote_users', // Check if current user can create users, shop managers are not allowed to create users. 'edit' => 'edit_users', 'delete' => 'delete_users', 'batch' => 'promote_users', ); // Check to allow shop_managers to manage only customers. if ( in_array( $context, array( 'edit', 'delete' ), true ) && kkart_current_user_has_role( 'shop_manager' ) ) { $permission = false; $user_data = get_userdata( $object_id ); $shop_manager_editable_roles = apply_filters( 'kkart_shop_manager_editable_roles', array( 'customer' ) ); if ( isset( $user_data->roles ) ) { $can_manage_users = array_intersect( $user_data->roles, array_unique( $shop_manager_editable_roles ) ); // Check if Shop Manager can edit customer or with the is same shop manager. if ( 0 < count( $can_manage_users ) || intval( $object_id ) === intval( get_current_user_id() ) ) { $permission = current_user_can( $contexts[ $context ], $object_id ); } } } else { $permission = current_user_can( $contexts[ $context ], $object_id ); } return apply_filters( 'kkart_rest_check_permissions', $permission, $context, $object_id, 'user' ); } /** * Check permissions of product terms on REST API. * * @since 2.6.0 * @param string $taxonomy Taxonomy. * @param string $context Request context. * @param int $object_id Post ID. * @return bool */ function kkart_rest_check_product_term_permissions( $taxonomy, $context = 'read', $object_id = 0 ) { $contexts = array( 'read' => 'manage_terms', 'create' => 'edit_terms', 'edit' => 'edit_terms', 'delete' => 'delete_terms', 'batch' => 'edit_terms', ); $cap = $contexts[ $context ]; $taxonomy_object = get_taxonomy( $taxonomy ); $permission = current_user_can( $taxonomy_object->cap->$cap, $object_id ); return apply_filters( 'kkart_rest_check_permissions', $permission, $context, $object_id, $taxonomy ); } /** * Check manager permissions on REST API. * * @since 2.6.0 * @param string $object Object. * @param string $context Request context. * @return bool */ function kkart_rest_check_manager_permissions( $object, $context = 'read' ) { $objects = array( 'reports' => 'view_kkart_reports', 'settings' => 'manage_kkart', 'system_status' => 'manage_kkart', 'attributes' => 'manage_product_terms', 'shipping_methods' => 'manage_kkart', 'payment_gateways' => 'manage_kkart', 'webhooks' => 'manage_kkart', ); $permission = current_user_can( $objects[ $object ] ); return apply_filters( 'kkart_rest_check_permissions', $permission, $context, 0, $object ); } /** * Check product reviews permissions on REST API. * * @since 3.5.0 * @param string $context Request context. * @param string $object_id Object ID. * @return bool */ function kkart_rest_check_product_reviews_permissions( $context = 'read', $object_id = 0 ) { $permission = false; $contexts = array( 'read' => 'moderate_comments', 'create' => 'moderate_comments', 'edit' => 'moderate_comments', 'delete' => 'moderate_comments', 'batch' => 'moderate_comments', ); if ( isset( $contexts[ $context ] ) ) { $permission = current_user_can( $contexts[ $context ] ); } return apply_filters( 'kkart_rest_check_permissions', $permission, $context, $object_id, 'product_review' ); } PK!!PxIIclass-kkart-template-loader.phpnu[plugin_path() . '/templates/' . $cs_template; } else { $template = KKART()->plugin_path() . '/templates/' . $default_file; } } } return $template; } // Pagelayer template not found fix public static function template_loader_final( $template ) { if ( is_embed() ) { return $template; } if(!empty($template) && !file_exists($template)){ if(is_user_logged_in()){ $msg = 'Template not found. Please create template OR import template from kkart settings.'; }else{ $msg = 'Template not found. Please contact the store manager, they will help you.'; } wp_die($msg); } return $template; } /** * Get the default filename for a template. * * @since 3.0.0 * @return string */ private static function get_template_loader_default_file() { if ( is_singular( 'product' ) ) { $default_file = 'single-product.php'; } elseif ( is_product_taxonomy() ) { $object = get_queried_object(); if ( is_tax( 'product_cat' ) || is_tax( 'product_tag' ) ) { $default_file = 'taxonomy-' . $object->taxonomy . '.php'; } else { $default_file = 'archive-product.php'; } } elseif ( is_post_type_archive( 'product' ) || is_page( kkart_get_page_id( 'shop' ) ) ) { $default_file = self::$theme_support ? 'archive-product.php' : ''; } else { $default_file = ''; } return $default_file; } /** * Get an array of filenames to search for a given template. * * @since 3.0.0 * @param string $default_file The default file name. * @return string[] */ private static function get_template_loader_files( $default_file ) { $templates = apply_filters( 'kkart_template_loader_files', array(), $default_file ); $templates[] = 'kkart.php'; if ( is_page_template() ) { $page_template = get_page_template_slug(); if ( $page_template ) { $validated_file = validate_file( $page_template ); if ( 0 === $validated_file ) { $templates[] = $page_template; } else { error_log( "Kkart: Unable to validate template path: \"$page_template\". Error Code: $validated_file." ); } } } if ( is_singular( 'product' ) ) { $object = get_queried_object(); $name_decoded = urldecode( $object->post_name ); if ( $name_decoded !== $object->post_name ) { $templates[] = "single-product-{$name_decoded}.php"; } $templates[] = "single-product-{$object->post_name}.php"; } if ( is_product_taxonomy() ) { $object = get_queried_object(); $templates[] = 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php'; $templates[] = KKART()->template_path() . 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php'; $templates[] = 'taxonomy-' . $object->taxonomy . '.php'; $templates[] = KKART()->template_path() . 'taxonomy-' . $object->taxonomy . '.php'; if ( is_tax( 'product_cat' ) || is_tax( 'product_tag' ) ) { $cs_taxonomy = str_replace( '_', '-', $object->taxonomy ); $cs_default = str_replace( '_', '-', $default_file ); $templates[] = 'taxonomy-' . $object->taxonomy . '-' . $object->slug . '.php'; $templates[] = KKART()->template_path() . 'taxonomy-' . $cs_taxonomy . '-' . $object->slug . '.php'; $templates[] = 'taxonomy-' . $object->taxonomy . '.php'; $templates[] = KKART()->template_path() . 'taxonomy-' . $cs_taxonomy . '.php'; $templates[] = $cs_default; } } $templates[] = $default_file; if ( isset( $cs_default ) ) { $templates[] = KKART()->template_path() . $cs_default; } $templates[] = KKART()->template_path() . $default_file; return array_unique( $templates ); } /** * Load comments template. * * @param string $template template to load. * @return string */ public static function comments_template_loader( $template ) { if ( get_post_type() !== 'product' ) { return $template; } $check_dirs = array( trailingslashit( get_stylesheet_directory() ) . KKART()->template_path(), trailingslashit( get_template_directory() ) . KKART()->template_path(), trailingslashit( get_stylesheet_directory() ), trailingslashit( get_template_directory() ), trailingslashit( KKART()->plugin_path() ) . 'templates/', ); if ( KKART_TEMPLATE_DEBUG_MODE ) { $check_dirs = array( array_pop( $check_dirs ) ); } foreach ( $check_dirs as $dir ) { if ( file_exists( trailingslashit( $dir ) . 'single-product-reviews.php' ) ) { return trailingslashit( $dir ) . 'single-product-reviews.php'; } } } /** * Unsupported theme compatibility methods. */ /** * Hook in methods to enhance the unsupported theme experience on pages. * * @since 3.3.0 */ public static function unsupported_theme_init() { if ( 0 < self::$shop_page_id ) { if ( is_product_taxonomy() ) { self::unsupported_theme_tax_archive_init(); } elseif ( is_product() ) { self::unsupported_theme_product_page_init(); } else { self::unsupported_theme_shop_page_init(); } } } /** * Hook in methods to enhance the unsupported theme experience on the Shop page. * * @since 3.3.0 */ private static function unsupported_theme_shop_page_init() { add_filter( 'the_content', array( __CLASS__, 'unsupported_theme_shop_content_filter' ), 10 ); add_filter( 'the_title', array( __CLASS__, 'unsupported_theme_title_filter' ), 10, 2 ); add_filter( 'comments_number', array( __CLASS__, 'unsupported_theme_comments_number_filter' ) ); } /** * Hook in methods to enhance the unsupported theme experience on Product pages. * * @since 3.3.0 */ private static function unsupported_theme_product_page_init() { add_filter( 'the_content', array( __CLASS__, 'unsupported_theme_product_content_filter' ), 10 ); add_filter( 'post_thumbnail_html', array( __CLASS__, 'unsupported_theme_single_featured_image_filter' ) ); add_filter( 'kkart_product_tabs', array( __CLASS__, 'unsupported_theme_remove_review_tab' ) ); remove_action( 'kkart_before_main_content', 'kkart_output_content_wrapper', 10 ); remove_action( 'kkart_after_main_content', 'kkart_output_content_wrapper_end', 10 ); add_theme_support( 'kkart-product-gallery-zoom' ); add_theme_support( 'kkart-product-gallery-lightbox' ); add_theme_support( 'kkart-product-gallery-slider' ); } /** * Enhance the unsupported theme experience on Product Category and Attribute pages by rendering * those pages using the single template and shortcode-based content. To do this we make a dummy * post and set a shortcode as the post content. This approach is adapted from bbPress. * * @since 3.3.0 */ private static function unsupported_theme_tax_archive_init() { global $wp_query, $post; $queried_object = get_queried_object(); $args = self::get_current_shop_view_args(); $shortcode_args = array( 'page' => $args->page, 'columns' => $args->columns, 'rows' => $args->rows, 'orderby' => '', 'order' => '', 'paginate' => true, 'cache' => false, ); if ( is_product_category() ) { $shortcode_args['category'] = sanitize_title( $queried_object->slug ); } elseif ( taxonomy_is_product_attribute( $queried_object->taxonomy ) ) { $shortcode_args['attribute'] = sanitize_title( $queried_object->taxonomy ); $shortcode_args['terms'] = sanitize_title( $queried_object->slug ); } elseif ( is_product_tag() ) { $shortcode_args['tag'] = sanitize_title( $queried_object->slug ); } else { // Default theme archive for all other taxonomies. return; } // Description handling. if ( ! empty( $queried_object->description ) && ( empty( $_GET['product-page'] ) || 1 === absint( $_GET['product-page'] ) ) ) { // WPCS: input var ok, CSRF ok. $prefix = '
' . kkart_format_content( $queried_object->description ) . '
'; // WPCS: XSS ok. } else { $prefix = ''; } add_filter( 'kkart_shortcode_products_query', array( __CLASS__, 'unsupported_archive_layered_nav_compatibility' ) ); $shortcode = new KKART_Shortcode_Products( $shortcode_args ); remove_filter( 'kkart_shortcode_products_query', array( __CLASS__, 'unsupported_archive_layered_nav_compatibility' ) ); $shop_page = get_post( self::$shop_page_id ); $dummy_post_properties = array( 'ID' => 0, 'post_status' => 'publish', 'post_author' => $shop_page->post_author, 'post_parent' => 0, 'post_type' => 'page', 'post_date' => $shop_page->post_date, 'post_date_gmt' => $shop_page->post_date_gmt, 'post_modified' => $shop_page->post_modified, 'post_modified_gmt' => $shop_page->post_modified_gmt, 'post_content' => $prefix . $shortcode->get_content(), 'post_title' => kkart_clean( $queried_object->name ), 'post_excerpt' => '', 'post_content_filtered' => '', 'post_mime_type' => '', 'post_password' => '', 'post_name' => $queried_object->slug, 'guid' => '', 'menu_order' => 0, 'pinged' => '', 'to_ping' => '', 'ping_status' => '', 'comment_status' => 'closed', 'comment_count' => 0, 'filter' => 'raw', ); // Set the $post global. $post = new WP_Post( (object) $dummy_post_properties ); // @codingStandardsIgnoreLine. // Copy the new post global into the main $wp_query. $wp_query->post = $post; $wp_query->posts = array( $post ); // Prevent comments form from appearing. $wp_query->post_count = 1; $wp_query->is_404 = false; $wp_query->is_page = true; $wp_query->is_single = true; $wp_query->is_archive = false; $wp_query->is_tax = true; $wp_query->max_num_pages = 0; // Prepare everything for rendering. setup_postdata( $post ); remove_all_filters( 'the_content' ); remove_all_filters( 'the_excerpt' ); add_filter( 'template_include', array( __CLASS__, 'force_single_template_filter' ) ); } /** * Add layered nav args to WP_Query args generated by the 'products' shortcode. * * @since 3.3.4 * @param array $query WP_Query args. * @return array */ public static function unsupported_archive_layered_nav_compatibility( $query ) { foreach ( KKART()->query->get_layered_nav_chosen_attributes() as $taxonomy => $data ) { $query['tax_query'][] = array( 'taxonomy' => $taxonomy, 'field' => 'slug', 'terms' => $data['terms'], 'operator' => 'and' === $data['query_type'] ? 'AND' : 'IN', 'include_children' => false, ); } return $query; } /** * Force the loading of one of the single templates instead of whatever template was about to be loaded. * * @since 3.3.0 * @param string $template Path to template. * @return string */ public static function force_single_template_filter( $template ) { $possible_templates = array( 'page', 'single', 'singular', 'index', ); foreach ( $possible_templates as $possible_template ) { $path = get_query_template( $possible_template ); if ( $path ) { return $path; } } return $template; } /** * Get information about the current shop page view. * * @since 3.3.0 * @return array */ private static function get_current_shop_view_args() { return (object) array( 'page' => absint( max( 1, absint( get_query_var( 'paged' ) ) ) ), 'columns' => kkart_get_default_products_per_row(), 'rows' => kkart_get_default_product_rows_per_page(), ); } /** * Filter the title and insert Kkart content on the shop page. * * For non-KKART themes, this will setup the main shop page to be shortcode based to improve default appearance. * * @since 3.3.0 * @param string $title Existing title. * @param int $id ID of the post being filtered. * @return string */ public static function unsupported_theme_title_filter( $title, $id ) { if ( self::$theme_support || ! $id !== self::$shop_page_id ) { return $title; } if ( is_page( self::$shop_page_id ) || ( is_home() && 'page' === get_option( 'show_on_front' ) && absint( get_option( 'page_on_front' ) ) === self::$shop_page_id ) ) { $args = self::get_current_shop_view_args(); $title_suffix = array(); if ( $args->page > 1 ) { /* translators: %d: Page number. */ $title_suffix[] = sprintf( esc_html__( 'Page %d', 'kkart' ), $args->page ); } if ( $title_suffix ) { $title = $title . ' – ' . implode( ', ', $title_suffix ); } } return $title; } /** * Filter the content and insert Kkart content on the shop page. * * For non-KKART themes, this will setup the main shop page to be shortcode based to improve default appearance. * * @since 3.3.0 * @param string $content Existing post content. * @return string */ public static function unsupported_theme_shop_content_filter( $content ) { global $wp_query; if ( self::$theme_support || ! is_main_query() || ! in_the_loop() ) { return $content; } self::$in_content_filter = true; // Remove the filter we're in to avoid nested calls. remove_filter( 'the_content', array( __CLASS__, 'unsupported_theme_shop_content_filter' ) ); // Unsupported theme shop page. if ( is_page( self::$shop_page_id ) ) { $args = self::get_current_shop_view_args(); $shortcode = new KKART_Shortcode_Products( array_merge( KKART()->query->get_catalog_ordering_args(), array( 'page' => $args->page, 'columns' => $args->columns, 'rows' => $args->rows, 'orderby' => '', 'order' => '', 'paginate' => true, 'cache' => false, ) ), 'products' ); // Allow queries to run e.g. layered nav. add_action( 'pre_get_posts', array( KKART()->query, 'product_query' ) ); $content = $content . $shortcode->get_content(); // Remove actions and self to avoid nested calls. remove_action( 'pre_get_posts', array( KKART()->query, 'product_query' ) ); KKART()->query->remove_ordering_args(); } self::$in_content_filter = false; return $content; } /** * Filter the content and insert Kkart content on the shop page. * * For non-KKART themes, this will setup the main shop page to be shortcode based to improve default appearance. * * @since 3.3.0 * @param string $content Existing post content. * @return string */ public static function unsupported_theme_product_content_filter( $content ) { global $wp_query; if ( self::$theme_support || ! is_main_query() || ! in_the_loop() ) { return $content; } self::$in_content_filter = true; // Remove the filter we're in to avoid nested calls. remove_filter( 'the_content', array( __CLASS__, 'unsupported_theme_product_content_filter' ) ); if ( is_product() ) { $content = do_shortcode( '[product_page id="' . get_the_ID() . '" show_title=0 status="any"]' ); } self::$in_content_filter = false; return $content; } /** * Suppress the comments number on the Shop page for unsupported themes since there is no commenting on the Shop page. * * @since 3.4.5 * @param string $comments_number The comments number text. * @return string */ public static function unsupported_theme_comments_number_filter( $comments_number ) { if ( is_page( self::$shop_page_id ) ) { return ''; } return $comments_number; } /** * Are we filtering content for unsupported themes? * * @since 3.3.2 * @return bool */ public static function in_content_filter() { return (bool) self::$in_content_filter; } /** * Prevent the main featured image on product pages because there will be another featured image * in the gallery. * * @since 3.3.0 * @param string $html Img element HTML. * @return string */ public static function unsupported_theme_single_featured_image_filter( $html ) { if ( self::in_content_filter() || ! is_product() || ! is_main_query() ) { return $html; } return ''; } /** * Remove the Review tab and just use the regular comment form. * * @param array $tabs Tab info. * @return array */ public static function unsupported_theme_remove_review_tab( $tabs ) { unset( $tabs['reviews'] ); return $tabs; } } add_action( 'init', array( 'KKART_Template_Loader', 'init' ) ); PK!EDD!class-kkart-product-variation.phpnu[ '', 'sku' => '', 'manage_stock' => '', 'backorders' => '', 'stock_quantity' => '', 'weight' => '', 'length' => '', 'width' => '', 'height' => '', 'tax_class' => '', 'shipping_class_id' => '', 'image_id' => '', 'purchase_note' => '', ); /** * Override the default constructor to set custom defaults. * * @param int|KKART_Product|object $product Product to init. */ public function __construct( $product = 0 ) { $this->data['tax_class'] = 'parent'; $this->data['attribute_summary'] = ''; parent::__construct( $product ); } /** * Prefix for action and filter hooks on data. * * @since 3.0.0 * @return string */ protected function get_hook_prefix() { return 'kkart_product_variation_get_'; } /** * Get internal type. * * @return string */ public function get_type() { return 'variation'; } /** * If the stock level comes from another product ID. * * @since 3.0.0 * @return int */ public function get_stock_managed_by_id() { return 'parent' === $this->get_manage_stock() ? $this->get_parent_id() : $this->get_id(); } /** * Get the product's title. For variations this is the parent product name. * * @return string */ public function get_title() { return apply_filters( 'kkart_product_title', $this->parent_data['title'], $this ); } /** * Get product name with SKU or ID. Used within admin. * * @return string Formatted product name */ public function get_formatted_name() { if ( $this->get_sku() ) { $identifier = $this->get_sku(); } else { $identifier = '#' . $this->get_id(); } $formatted_variation_list = kkart_get_formatted_variation( $this, true, true, true ); return sprintf( '%2$s (%1$s)', $identifier, $this->get_name() ) . '' . $formatted_variation_list . ''; } /** * Get variation attribute values. Keys are prefixed with attribute_, as stored, unless $with_prefix is false. * * @param bool $with_prefix Whether keys should be prepended with attribute_ or not, default is true. * @return array of attributes and their values for this variation. */ public function get_variation_attributes( $with_prefix = true ) { $attributes = $this->get_attributes(); $variation_attributes = array(); $prefix = $with_prefix ? 'attribute_' : ''; foreach ( $attributes as $key => $value ) { $variation_attributes[ $prefix . $key ] = $value; } return $variation_attributes; } /** * Returns a single product attribute as a string. * * @param string $attribute to get. * @return string */ public function get_attribute( $attribute ) { $attributes = $this->get_attributes(); $attribute = sanitize_title( $attribute ); if ( isset( $attributes[ $attribute ] ) ) { $value = $attributes[ $attribute ]; $term = taxonomy_exists( $attribute ) ? get_term_by( 'slug', $value, $attribute ) : false; return ! is_wp_error( $term ) && $term ? $term->name : $value; } $att_str = 'pa_' . $attribute; if ( isset( $attributes[ $att_str ] ) ) { $value = $attributes[ $att_str ]; $term = taxonomy_exists( $att_str ) ? get_term_by( 'slug', $value, $att_str ) : false; return ! is_wp_error( $term ) && $term ? $term->name : $value; } return ''; } /** * Wrapper for get_permalink. Adds this variations attributes to the URL. * * @param array|null $item_object item array If a cart or order item is passed, we can get a link containing the exact attributes selected for the variation, rather than the default attributes. * @return string */ public function get_permalink( $item_object = null ) { $url = get_permalink( $this->get_parent_id() ); if ( ! empty( $item_object['variation'] ) ) { $data = $item_object['variation']; } elseif ( ! empty( $item_object['item_meta_array'] ) ) { $data_keys = array_map( 'kkart_variation_attribute_name', wp_list_pluck( $item_object['item_meta_array'], 'key' ) ); $data_values = wp_list_pluck( $item_object['item_meta_array'], 'value' ); $data = array_intersect_key( array_combine( $data_keys, $data_values ), $this->get_variation_attributes() ); } else { $data = $this->get_variation_attributes(); } $data = array_filter( $data, 'kkart_array_filter_default_attributes' ); if ( empty( $data ) ) { return $url; } // Filter and encode keys and values so this is not broken by add_query_arg. $data = array_map( 'urlencode', $data ); $keys = array_map( 'urlencode', array_keys( $data ) ); return add_query_arg( array_combine( $keys, $data ), $url ); } /** * Get the add to url used mainly in loops. * * @return string */ public function add_to_cart_url() { $url = $this->is_purchasable() ? remove_query_arg( 'added-to-cart', add_query_arg( array( 'variation_id' => $this->get_id(), 'add-to-cart' => $this->get_parent_id(), ), $this->get_permalink() ) ) : $this->get_permalink(); return apply_filters( 'kkart_product_add_to_cart_url', $url, $this ); } /** * Get SKU (Stock-keeping unit) - product unique ID. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_sku( $context = 'view' ) { $value = $this->get_prop( 'sku', $context ); // Inherit value from parent. if ( 'view' === $context && empty( $value ) ) { $value = apply_filters( $this->get_hook_prefix() . 'sku', $this->parent_data['sku'], $this ); } return $value; } /** * Returns the product's weight. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_weight( $context = 'view' ) { $value = $this->get_prop( 'weight', $context ); // Inherit value from parent. if ( 'view' === $context && empty( $value ) ) { $value = apply_filters( $this->get_hook_prefix() . 'weight', $this->parent_data['weight'], $this ); } return $value; } /** * Returns the product length. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_length( $context = 'view' ) { $value = $this->get_prop( 'length', $context ); // Inherit value from parent. if ( 'view' === $context && empty( $value ) ) { $value = apply_filters( $this->get_hook_prefix() . 'length', $this->parent_data['length'], $this ); } return $value; } /** * Returns the product width. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_width( $context = 'view' ) { $value = $this->get_prop( 'width', $context ); // Inherit value from parent. if ( 'view' === $context && empty( $value ) ) { $value = apply_filters( $this->get_hook_prefix() . 'width', $this->parent_data['width'], $this ); } return $value; } /** * Returns the product height. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_height( $context = 'view' ) { $value = $this->get_prop( 'height', $context ); // Inherit value from parent. if ( 'view' === $context && empty( $value ) ) { $value = apply_filters( $this->get_hook_prefix() . 'height', $this->parent_data['height'], $this ); } return $value; } /** * Returns the tax class. * * Does not use get_prop so it can handle 'parent' inheritance correctly. * * @param string $context view, edit, or unfiltered. * @return string */ public function get_tax_class( $context = 'view' ) { $value = null; if ( array_key_exists( 'tax_class', $this->data ) ) { $value = array_key_exists( 'tax_class', $this->changes ) ? $this->changes['tax_class'] : $this->data['tax_class']; if ( 'edit' !== $context && 'parent' === $value ) { $value = $this->parent_data['tax_class']; } if ( 'view' === $context ) { $value = apply_filters( $this->get_hook_prefix() . 'tax_class', $value, $this ); } } return $value; } /** * Return if product manage stock. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return boolean|string true, false, or parent. */ public function get_manage_stock( $context = 'view' ) { $value = $this->get_prop( 'manage_stock', $context ); // Inherit value from parent. if ( 'view' === $context && false === $value && true === kkart_string_to_bool( $this->parent_data['manage_stock'] ) ) { $value = 'parent'; } return $value; } /** * Returns number of items available for sale. * * @param string $context What the value is for. Valid values are view and edit. * @return int|null */ public function get_stock_quantity( $context = 'view' ) { $value = $this->get_prop( 'stock_quantity', $context ); // Inherit value from parent. if ( 'view' === $context && 'parent' === $this->get_manage_stock() ) { $value = apply_filters( $this->get_hook_prefix() . 'stock_quantity', $this->parent_data['stock_quantity'], $this ); } return $value; } /** * Get backorders. * * @param string $context What the value is for. Valid values are view and edit. * @since 3.0.0 * @return string yes no or notify */ public function get_backorders( $context = 'view' ) { $value = $this->get_prop( 'backorders', $context ); // Inherit value from parent. if ( 'view' === $context && 'parent' === $this->get_manage_stock() ) { $value = apply_filters( $this->get_hook_prefix() . 'backorders', $this->parent_data['backorders'], $this ); } return $value; } /** * Get main image ID. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_image_id( $context = 'view' ) { $image_id = $this->get_prop( 'image_id', $context ); if ( 'view' === $context && ! $image_id ) { $image_id = apply_filters( $this->get_hook_prefix() . 'image_id', $this->parent_data['image_id'], $this ); } return $image_id; } /** * Get purchase note. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_purchase_note( $context = 'view' ) { $value = $this->get_prop( 'purchase_note', $context ); // Inherit value from parent. if ( 'view' === $context && empty( $value ) ) { $value = apply_filters( $this->get_hook_prefix() . 'purchase_note', $this->parent_data['purchase_note'], $this ); } return $value; } /** * Get shipping class ID. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_shipping_class_id( $context = 'view' ) { $shipping_class_id = $this->get_prop( 'shipping_class_id', $context ); if ( 'view' === $context && ! $shipping_class_id ) { $shipping_class_id = apply_filters( $this->get_hook_prefix() . 'shipping_class_id', $this->parent_data['shipping_class_id'], $this ); } return $shipping_class_id; } /** * Get catalog visibility. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_catalog_visibility( $context = 'view' ) { return apply_filters( $this->get_hook_prefix() . 'catalog_visibility', $this->parent_data['catalog_visibility'], $this ); } /** * Get attribute summary. * * By default, attribute summary contains comma-delimited 'attribute_name: attribute_value' pairs for all attributes. * * @param string $context What the value is for. Valid values are view and edit. * * @since 3.6.0 * @return string */ public function get_attribute_summary( $context = 'view' ) { return $this->get_prop( 'attribute_summary', $context ); } /** * Set attribute summary. * * By default, attribute summary contains comma-delimited 'attribute_name: attribute_value' pairs for all attributes. * * @since 3.6.0 * @param string $attribute_summary Summary of attribute names and values assigned to the variation. */ public function set_attribute_summary( $attribute_summary ) { $this->set_prop( 'attribute_summary', $attribute_summary ); } /* |-------------------------------------------------------------------------- | CRUD methods |-------------------------------------------------------------------------- */ /** * Set the parent data array for this variation. * * @since 3.0.0 * @param array $parent_data parent data array for this variation. */ public function set_parent_data( $parent_data ) { $parent_data = wp_parse_args( $parent_data, array( 'title' => '', 'status' => '', 'sku' => '', 'manage_stock' => 'no', 'backorders' => 'no', 'stock_quantity' => '', 'weight' => '', 'length' => '', 'width' => '', 'height' => '', 'tax_class' => '', 'shipping_class_id' => 0, 'image_id' => 0, 'purchase_note' => '', 'catalog_visibility' => 'visible', ) ); // Normalize tax class. $parent_data['tax_class'] = sanitize_title( $parent_data['tax_class'] ); $parent_data['tax_class'] = 'standard' === $parent_data['tax_class'] ? '' : $parent_data['tax_class']; $valid_classes = $this->get_valid_tax_classes(); if ( ! in_array( $parent_data['tax_class'], $valid_classes, true ) ) { $parent_data['tax_class'] = ''; } $this->parent_data = $parent_data; } /** * Get the parent data array for this variation. * * @since 3.0.0 * @return array */ public function get_parent_data() { return $this->parent_data; } /** * Set attributes. Unlike the parent product which uses terms, variations are assigned * specific attributes using name value pairs. * * @param array $raw_attributes array of raw attributes. */ public function set_attributes( $raw_attributes ) { $raw_attributes = (array) $raw_attributes; $attributes = array(); foreach ( $raw_attributes as $key => $value ) { // Remove attribute prefix which meta gets stored with. if ( 0 === strpos( $key, 'attribute_' ) ) { $key = substr( $key, 10 ); } $attributes[ $key ] = $value; } $this->set_prop( 'attributes', $attributes ); } /** * Returns whether or not the product has any visible attributes. * * Variations are mapped to specific attributes unlike products, and the return * value of ->get_attributes differs. Therefore this returns false. * * @return boolean */ public function has_attributes() { return false; } /* |-------------------------------------------------------------------------- | Conditionals |-------------------------------------------------------------------------- */ /** * Returns false if the product cannot be bought. * Override abstract method so that: i) Disabled variations are not be purchasable by admins. ii) Enabled variations are not purchasable if the parent product is not purchasable. * * @return bool */ public function is_purchasable() { return apply_filters( 'kkart_variation_is_purchasable', $this->variation_is_visible() && parent::is_purchasable() && ( 'publish' === $this->parent_data['status'] || current_user_can( 'edit_post', $this->get_parent_id() ) ), $this ); } /** * Controls whether this particular variation will appear greyed-out (inactive) or not (active). * Used by extensions to make incompatible variations appear greyed-out, etc. * Other possible uses: prevent out-of-stock variations from being selected. * * @return bool */ public function variation_is_active() { return apply_filters( 'kkart_variation_is_active', true, $this ); } /** * Checks if this particular variation is visible. Invisible variations are enabled and can be selected, but no price / stock info is displayed. * Instead, a suitable 'unavailable' message is displayed. * Invisible by default: Disabled variations and variations with an empty price. * * @return bool */ public function variation_is_visible() { return apply_filters( 'kkart_variation_is_visible', 'publish' === get_post_status( $this->get_id() ) && '' !== $this->get_price(), $this->get_id(), $this->get_parent_id(), $this ); } /** * Return valid tax classes. Adds 'parent' to the default list of valid tax classes. * * @return array valid tax classes */ protected function get_valid_tax_classes() { $valid_classes = KKART_Tax::get_tax_class_slugs(); $valid_classes[] = 'parent'; return $valid_classes; } /** * Delete variation, set the ID to 0, and return result. * * @since 4.4.0 * @param bool $force_delete Should the variation be deleted permanently. * @return bool result */ public function delete( $force_delete = false ) { $variation_id = $this->get_id(); if ( ! parent::delete( $force_delete ) ) { return false; } return true; } } PK!IS/UU class-kkart-product-variable.phpnu[is_purchasable() ? __( 'Select options', 'kkart' ) : __( 'Read more', 'kkart' ), $this ); } /** * Get the add to cart button text description - used in aria tags. * * @since 3.3.0 * @return string */ public function add_to_cart_description() { /* translators: %s: Product title */ return apply_filters( 'kkart_product_add_to_cart_description', sprintf( __( 'Select options for “%s”', 'kkart' ), $this->get_name() ), $this ); } /** * Get an array of all sale and regular prices from all variations. This is used for example when displaying the price range at variable product level or seeing if the variable product is on sale. * * @param bool $for_display If true, prices will be adapted for display based on the `kkart_tax_display_shop` setting (including or excluding taxes). * @return array Array of RAW prices, regular prices, and sale prices with keys set to variation ID. */ public function get_variation_prices( $for_display = false ) { $prices = $this->data_store->read_price_data( $this, $for_display ); foreach ( $prices as $price_key => $variation_prices ) { $prices[ $price_key ] = $this->sort_variation_prices( $variation_prices ); } return $prices; } /** * Get the min or max variation regular price. * * @param string $min_or_max Min or max price. * @param boolean $for_display If true, prices will be adapted for display based on the `kkart_tax_display_shop` setting (including or excluding taxes). * @return string */ public function get_variation_regular_price( $min_or_max = 'min', $for_display = false ) { $prices = $this->get_variation_prices( $for_display ); $price = 'min' === $min_or_max ? current( $prices['regular_price'] ) : end( $prices['regular_price'] ); return apply_filters( 'kkart_get_variation_regular_price', $price, $this, $min_or_max, $for_display ); } /** * Get the min or max variation sale price. * * @param string $min_or_max Min or max price. * @param boolean $for_display If true, prices will be adapted for display based on the `kkart_tax_display_shop` setting (including or excluding taxes). * @return string */ public function get_variation_sale_price( $min_or_max = 'min', $for_display = false ) { $prices = $this->get_variation_prices( $for_display ); $price = 'min' === $min_or_max ? current( $prices['sale_price'] ) : end( $prices['sale_price'] ); return apply_filters( 'kkart_get_variation_sale_price', $price, $this, $min_or_max, $for_display ); } /** * Get the min or max variation (active) price. * * @param string $min_or_max Min or max price. * @param boolean $for_display If true, prices will be adapted for display based on the `kkart_tax_display_shop` setting (including or excluding taxes). * @return string */ public function get_variation_price( $min_or_max = 'min', $for_display = false ) { $prices = $this->get_variation_prices( $for_display ); $price = 'min' === $min_or_max ? current( $prices['price'] ) : end( $prices['price'] ); return apply_filters( 'kkart_get_variation_price', $price, $this, $min_or_max, $for_display ); } /** * Returns the price in html format. * * Note: Variable prices do not show suffixes like other product types. This * is due to some things like tax classes being set at variation level which * could differ from the parent price. The only way to show accurate prices * would be to load the variation and get it's price, which adds extra * overhead and still has edge cases where the values would be inaccurate. * * Additionally, ranges of prices no longer show 'striked out' sale prices * due to the strings being very long and unclear/confusing. A single range * is shown instead. * * @param string $price Price (default: ''). * @return string */ public function get_price_html( $price = '' ) { $prices = $this->get_variation_prices( true ); if ( empty( $prices['price'] ) ) { $price = apply_filters( 'kkart_variable_empty_price_html', '', $this ); } else { $min_price = current( $prices['price'] ); $max_price = end( $prices['price'] ); $min_reg_price = current( $prices['regular_price'] ); $max_reg_price = end( $prices['regular_price'] ); if ( $min_price !== $max_price ) { $price = kkart_format_price_range( $min_price, $max_price ); } elseif ( $this->is_on_sale() && $min_reg_price === $max_reg_price ) { $price = kkart_format_sale_price( kkart_price( $max_reg_price ), kkart_price( $min_price ) ); } else { $price = kkart_price( $min_price ); } $price = apply_filters( 'kkart_variable_price_html', $price . $this->get_price_suffix(), $this ); } return apply_filters( 'kkart_get_price_html', $price, $this ); } /** * Get the suffix to display after prices > 0. * * This is skipped if the suffix * has dynamic values such as {price_excluding_tax} for variable products. * * @see get_price_html for an explanation as to why. * @param string $price Price to calculate, left blank to just use get_price(). * @param integer $qty Quantity passed on to get_price_including_tax() or get_price_excluding_tax(). * @return string */ public function get_price_suffix( $price = '', $qty = 1 ) { $suffix = get_option( 'kkart_price_display_suffix' ); if ( strstr( $suffix, '{' ) ) { return apply_filters( 'kkart_get_price_suffix', '', $this, $price, $qty ); } else { return parent::get_price_suffix( $price, $qty ); } } /** * Return a products child ids. * * This is lazy loaded as it's not used often and does require several queries. * * @param bool|string $visible_only Visible only. * @return array Children ids */ public function get_children( $visible_only = '' ) { if ( is_bool( $visible_only ) ) { kkart_deprecated_argument( 'visible_only', '3.0', 'KKART_Product_Variable::get_visible_children' ); return $visible_only ? $this->get_visible_children() : $this->get_children(); } if ( null === $this->children ) { $children = $this->data_store->read_children( $this ); $this->set_children( $children['all'] ); $this->set_visible_children( $children['visible'] ); } return apply_filters( 'kkart_get_children', $this->children, $this, false ); } /** * Return a products child ids - visible only. * * This is lazy loaded as it's not used often and does require several queries. * * @since 3.0.0 * @return array Children ids */ public function get_visible_children() { if ( null === $this->visible_children ) { $children = $this->data_store->read_children( $this ); $this->set_children( $children['all'] ); $this->set_visible_children( $children['visible'] ); } return apply_filters( 'kkart_get_children', $this->visible_children, $this, true ); } /** * Return an array of attributes used for variations, as well as their possible values. * * This is lazy loaded as it's not used often and does require several queries. * * @return array Attributes and their available values */ public function get_variation_attributes() { if ( null === $this->variation_attributes ) { $this->variation_attributes = $this->data_store->read_variation_attributes( $this ); } return $this->variation_attributes; } /** * If set, get the default attributes for a variable product. * * @param string $attribute_name Attribute name. * @return string */ public function get_variation_default_attribute( $attribute_name ) { $defaults = $this->get_default_attributes(); $attribute_name = sanitize_title( $attribute_name ); return isset( $defaults[ $attribute_name ] ) ? $defaults[ $attribute_name ] : ''; } /** * Variable products themselves cannot be downloadable. * * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function get_downloadable( $context = 'view' ) { return false; } /** * Variable products themselves cannot be virtual. * * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function get_virtual( $context = 'view' ) { return false; } /** * Get an array of available variations for the current product. * * @param string $return Optional. The format to return the results in. Can be 'array' to return an array of variation data or 'objects' for the product objects. Default 'array'. * * @return array[]|KKART_Product_Variation[] */ public function get_available_variations( $return = 'array' ) { $variation_ids = $this->get_children(); $available_variations = array(); if ( is_callable( '_prime_post_caches' ) ) { _prime_post_caches( $variation_ids ); } foreach ( $variation_ids as $variation_id ) { $variation = kkart_get_product( $variation_id ); // Hide out of stock variations if 'Hide out of stock items from the catalog' is checked. if ( ! $variation || ! $variation->exists() || ( 'yes' === get_option( 'kkart_hide_out_of_stock_items' ) && ! $variation->is_in_stock() ) ) { continue; } // Filter 'kkart_hide_invisible_variations' to optionally hide invisible variations (disabled variations and variations with empty price). if ( apply_filters( 'kkart_hide_invisible_variations', true, $this->get_id(), $variation ) && ! $variation->variation_is_visible() ) { continue; } if ( 'array' === $return ) { $available_variations[] = $this->get_available_variation( $variation ); } else { $available_variations[] = $variation; } } if ( 'array' === $return ) { $available_variations = array_values( array_filter( $available_variations ) ); } return $available_variations; } /** * Check if a given variation is currently available. * * @param KKART_Product_Variation $variation Variation to check. * * @return bool True if the variation is available, false otherwise. */ private function variation_is_available( KKART_Product_Variation $variation ) { // Hide out of stock variations if 'Hide out of stock items from the catalog' is checked. if ( ! $variation || ! $variation->exists() || ( 'yes' === get_option( 'kkart_hide_out_of_stock_items' ) && ! $variation->is_in_stock() ) ) { return false; } // Filter 'kkart_hide_invisible_variations' to optionally hide invisible variations (disabled variations and variations with empty price). if ( apply_filters( 'kkart_hide_invisible_variations', true, $this->get_id(), $variation ) && ! $variation->variation_is_visible() ) { return false; } return true; } /** * Returns an array of data for a variation. Used in the add to cart form. * * @since 2.4.0 * @param KKART_Product $variation Variation product object or ID. * @return array|bool */ public function get_available_variation( $variation ) { if ( is_numeric( $variation ) ) { $variation = kkart_get_product( $variation ); } if ( ! $variation instanceof KKART_Product_Variation ) { return false; } // See if prices should be shown for each variation after selection. $show_variation_price = apply_filters( 'kkart_show_variation_price', $variation->get_price() === '' || $this->get_variation_sale_price( 'min' ) !== $this->get_variation_sale_price( 'max' ) || $this->get_variation_regular_price( 'min' ) !== $this->get_variation_regular_price( 'max' ), $this, $variation ); return apply_filters( 'kkart_available_variation', array( 'attributes' => $variation->get_variation_attributes(), 'availability_html' => kkart_get_stock_html( $variation ), 'backorders_allowed' => $variation->backorders_allowed(), 'dimensions' => $variation->get_dimensions( false ), 'dimensions_html' => kkart_format_dimensions( $variation->get_dimensions( false ) ), 'display_price' => kkart_get_price_to_display( $variation ), 'display_regular_price' => kkart_get_price_to_display( $variation, array( 'price' => $variation->get_regular_price() ) ), 'image' => kkart_get_product_attachment_props( $variation->get_image_id() ), 'image_id' => $variation->get_image_id(), 'is_downloadable' => $variation->is_downloadable(), 'is_in_stock' => $variation->is_in_stock(), 'is_purchasable' => $variation->is_purchasable(), 'is_sold_individually' => $variation->is_sold_individually() ? 'yes' : 'no', 'is_virtual' => $variation->is_virtual(), 'max_qty' => 0 < $variation->get_max_purchase_quantity() ? $variation->get_max_purchase_quantity() : '', 'min_qty' => $variation->get_min_purchase_quantity(), 'price_html' => $show_variation_price ? '' . $variation->get_price_html() . '' : '', 'sku' => $variation->get_sku(), 'variation_description' => kkart_format_content( $variation->get_description() ), 'variation_id' => $variation->get_id(), 'variation_is_active' => $variation->variation_is_active(), 'variation_is_visible' => $variation->variation_is_visible(), 'weight' => $variation->get_weight(), 'weight_html' => kkart_format_weight( $variation->get_weight() ), ), $this, $variation ); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- */ /** * Sets an array of variation attributes. * * @since 3.0.0 * @param array $variation_attributes Attributes list. */ public function set_variation_attributes( $variation_attributes ) { $this->variation_attributes = $variation_attributes; } /** * Sets an array of children for the product. * * @since 3.0.0 * @param array $children Children products. */ public function set_children( $children ) { $this->children = array_filter( wp_parse_id_list( (array) $children ) ); } /** * Sets an array of visible children only. * * @since 3.0.0 * @param array $visible_children List of visible children products. */ public function set_visible_children( $visible_children ) { $this->visible_children = array_filter( wp_parse_id_list( (array) $visible_children ) ); } /* |-------------------------------------------------------------------------- | CRUD methods |-------------------------------------------------------------------------- */ /** * Ensure properties are set correctly before save. * * @since 3.0.0 */ public function validate_props() { parent::validate_props(); if ( ! $this->get_manage_stock() ) { $this->data_store->sync_stock_status( $this ); } } /** * Save data (either create or update depending on if we are working on an existing product). * * @since 3.0.0 */ public function save() { $this->validate_props(); if ( ! $this->data_store ) { return $this->get_id(); } /** * Trigger action before saving to the DB. Allows you to adjust object props before save. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store The data store persisting the data. */ do_action( 'kkart_before_' . $this->object_type . '_object_save', $this, $this->data_store ); // Get names before save. $previous_name = $this->data['name']; $new_name = $this->get_name( 'edit' ); if ( $this->get_id() ) { $this->data_store->update( $this ); } else { $this->data_store->create( $this ); } $this->data_store->sync_variation_names( $this, $previous_name, $new_name ); $this->data_store->sync_managed_variation_stock_status( $this ); /** * Trigger action after saving to the DB. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store The data store persisting the data. */ do_action( 'kkart_after_' . $this->object_type . '_object_save', $this, $this->data_store ); return $this->get_id(); } /* |-------------------------------------------------------------------------- | Conditionals |-------------------------------------------------------------------------- */ /** * Returns whether or not the product is on sale. * * @param string $context What the value is for. Valid values are view and edit. What the value is for. Valid values are view and edit. * @return bool */ public function is_on_sale( $context = 'view' ) { $prices = $this->get_variation_prices(); $on_sale = $prices['regular_price'] !== $prices['sale_price'] && $prices['sale_price'] === $prices['price']; return 'view' === $context ? apply_filters( 'kkart_product_is_on_sale', $on_sale, $this ) : $on_sale; } /** * Is a child in stock? * * @return boolean */ public function child_is_in_stock() { return $this->data_store->child_is_in_stock( $this ); } /** * Is a child on backorder? * * @since 3.3.0 * @return boolean */ public function child_is_on_backorder() { return $this->data_store->child_has_stock_status( $this, 'onbackorder' ); } /** * Does a child have a weight set? * * @return boolean */ public function child_has_weight() { $transient_name = 'kkart_child_has_weight_' . $this->get_id(); $has_weight = get_transient( $transient_name ); if ( false === $has_weight ) { $has_weight = $this->data_store->child_has_weight( $this ); set_transient( $transient_name, (int) $has_weight, DAY_IN_SECONDS * 30 ); } return (bool) $has_weight; } /** * Does a child have dimensions set? * * @return boolean */ public function child_has_dimensions() { $transient_name = 'kkart_child_has_dimensions_' . $this->get_id(); $has_dimension = get_transient( $transient_name ); if ( false === $has_dimension ) { $has_dimension = $this->data_store->child_has_dimensions( $this ); set_transient( $transient_name, (int) $has_dimension, DAY_IN_SECONDS * 30 ); } return (bool) $has_dimension; } /** * Returns whether or not the product has dimensions set. * * @return bool */ public function has_dimensions() { return parent::has_dimensions() || $this->child_has_dimensions(); } /** * Returns whether or not the product has weight set. * * @return bool */ public function has_weight() { return parent::has_weight() || $this->child_has_weight(); } /** * Returns whether or not the product has additional options that need * selecting before adding to cart. * * @since 3.0.0 * @return boolean */ public function has_options() { return apply_filters( 'kkart_product_has_options', true, $this ); } /* |-------------------------------------------------------------------------- | Sync with child variations. |-------------------------------------------------------------------------- */ /** * Sync a variable product with it's children. These sync functions sync * upwards (from child to parent) when the variation is saved. * * @param KKART_Product|int $product Product object or ID for which you wish to sync. * @param bool $save If true, the product object will be saved to the DB before returning it. * @return KKART_Product Synced product object. */ public static function sync( $product, $save = true ) { if ( ! is_a( $product, 'KKART_Product' ) ) { $product = kkart_get_product( $product ); } if ( is_a( $product, 'KKART_Product_Variable' ) ) { $data_store = KKART_Data_Store::load( 'product-' . $product->get_type() ); $data_store->sync_price( $product ); $data_store->sync_stock_status( $product ); self::sync_attributes( $product ); // Legacy update of attributes. do_action( 'kkart_variable_product_sync_data', $product ); if ( $save ) { $product->save(); } } return $product; } /** * Sync parent stock status with the status of all children and save. * * @param KKART_Product|int $product Product object or ID for which you wish to sync. * @param bool $save If true, the product object will be saved to the DB before returning it. * @return KKART_Product Synced product object. */ public static function sync_stock_status( $product, $save = true ) { if ( ! is_a( $product, 'KKART_Product' ) ) { $product = kkart_get_product( $product ); } if ( is_a( $product, 'KKART_Product_Variable' ) ) { $data_store = KKART_Data_Store::load( 'product-' . $product->get_type() ); $data_store->sync_stock_status( $product ); if ( $save ) { $product->save(); } } return $product; } /** * Sort an associative array of $variation_id => $price pairs in order of min and max prices. * * @param array $prices associative array of $variation_id => $price pairs. * @return array */ protected function sort_variation_prices( $prices ) { asort( $prices ); return $prices; } } PK! body-props-settings.phpnu[get_date_on_sale_from( 'edit' ) ? $product->get_date_on_sale_from( 'edit' )->getOffsetTimestamp() : false; $sale_price_dates_to_timestamp = $product->get_date_on_sale_to( 'edit' ) ? $product->get_date_on_sale_to( 'edit' )->getOffsetTimestamp() : false; $sale_price_dates_from = $sale_price_dates_from_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_from_timestamp ) : ''; $sale_price_dates_to = $sale_price_dates_to_timestamp ? date_i18n( 'Y-m-d', $sale_price_dates_to_timestamp ) : ''; $downloads = (array) $product->get_downloads(); $_downloads = array(); // Covert downloads array for shortcode compatibility foreach($downloads as $kk => $vv){ $_downloads['names'][] = $vv['name']; $_downloads['hashes'][] = $vv['id']; $_downloads['urls'][] = $vv['file']; } $props = array( '_regular_price' => $product->get_regular_price('edit'), '_sale_price' => $product->get_sale_price('edit'), 'product_image_gallery' => $product->get_gallery_image_ids(), '_sale_price_dates_from' => esc_attr( $sale_price_dates_from ), '_sale_price_dates_to' => esc_attr( $sale_price_dates_to ), '_downloadable_files' => $_downloads ); foreach($props as $prop => $val){ $el['atts'][$prop] = $val; $el['oAtts'][$prop] = $val; } return $el; } // Set body property for the KKART product function kkart_body_props_settings($params){ global $post; $product = kkart_get_product($post); $params['kkart_gallery'] = array( 'product_image_gallery' => array( 'type' => 'multi_image', 'label' => __pl('product_gallery'), 'default' => ((!empty($product)) ? implode(',', $product->get_gallery_image_ids()) : ''), 'export-def' => 1, 'post' => 1, ), ); $params['kkart_pricing'] = array( '_downloadable' => array( 'type' => 'checkbox', 'label' => __pl('Is Downloadable'), 'post' => 1, ), '_regular_price' => array( 'type' => 'spinner', 'label' => __pl('Regular Price').'('.get_kkart_currency_symbol().')', 'min' => 0, 'post' => 1, ), '_sale_price' => array( 'type' => 'spinner', 'label' => __pl('Sale Price').'('.get_kkart_currency_symbol().')', 'min' => 0, 'post' => 1, ), 'sale_time' => array( 'type' => 'checkbox', 'label' => __pl('Sale Schedule'), ), '_sale_price_dates_from' => array( 'type' => 'datetime', 'label' => __pl('Sale Start Time'), 'req' => ['sale_time' => 'true'], 'post' => 1, ), '_sale_price_dates_to' => array( 'type' => 'datetime', 'label' => __pl('Sale End Time'), 'req' => ['sale_time' => 'true'], 'post' => 1, ), '_downloadable_files' => array( 'type' => 'downloadable_files', 'label' => __pl('Downloadable Files'), 'req' => ['_downloadable' => 'true'], ), '_download_limit' => array( 'type' => 'text', 'label' => __pl('Download Limit'), 'req' => ['_downloadable' => 'true'], 'desc' => __pl('Leave blank for unlimited re-downloads.'), ), '_download_expiry' => array( 'type' => 'text', 'label' => __pl('Download Expiry'), 'req' => ['_downloadable' => 'true'], 'desc' => __pl('Enter the number of days before a download link expires, or leave blank.'), ), '_tax_status' => array( 'type' => 'select', 'label' => __pl('Tax Status'), 'list' => array( 'taxable' => __pl('Taxable'), 'shipping' => __pl('Shipping Only'), 'none' => __pl('None'), ), 'default' => 'taxable', 'post' => 1, ), '_tax_class' => array( 'type' => 'select', 'label' => __pl('Tax Class'), 'list' => kkart_get_product_tax_class_options(), 'default' => 'standard', 'post' => 1, ), ); $params['kkart_inventory'] = array( '_sku' => array( 'type' => 'text', 'label' => __pl('SKU (Stock Keeping Unit)'), 'post' => 1, ), 'barcode' => array( 'type' => 'text', 'label' => __pl('Barcode (ISBN, UPC, GTIN, etc.)'), ), '_manage_stock' => array( 'type' => 'checkbox', 'label' => __pl('Track quantity'), 'post' => 1, ), '_stock' => array( 'type' => 'spinner', 'label' => __pl('Stock quantity'), 'default' => 1, 'post' => 1, 'req' => ['_manage_stock' => 'true'], ), '_backorders' => array( 'type' => 'select', 'label' => __pl('Allow backorders?'), 'post' => 1, 'list' => array( 'no' => __pl('Do not allow'), 'notify' => __pl('Allow, but notify customer'), 'yes' => __pl('Allow'), ), 'req' => ['_manage_stock' => 'true'] ), '_low_stock_amount' => array( 'type' => 'spinner', 'label' => __pl('Low stock threshold'), 'default' => 2, 'post' => 1, 'req' => ['_manage_stock' => 'true'] ), '_stock_status' => array( 'type' => 'select', 'label' => __pl('Stock status'), 'post' => 1, 'default' => 'instock', 'list' => array( 'instock' => __pl('In stock'), 'outofstock' => __pl('Out Of Stock'), 'onbackorder' => __pl('On Backorder'), ), 'req' => ['_manage_stock' => ''] ), '_sold_individually' => array( 'type' => 'checkbox', 'label' => __pl('Sold individually'), 'post' => 1, ), ); $params['kkart_shipping'] = array( '_virtual' => array( 'type' => 'checkbox', 'label' => __pl('Is Virtual'), 'post' => 1, ), '_weight' => array( 'type' => 'text', 'label' => __pl('Weight'), 'post' => 1, 'req' => ['_virtual' => ''], ), '_length' => array( 'type' => 'text', 'label' => __pl('Length'), 'post' => 1, 'req' => ['_virtual' => ''], ), '_width' => array( 'type' => 'text', 'label' => __pl('Width'), 'post' => 1, 'req' => ['_virtual' => ''], ), '_height' => array( 'type' => 'text', 'label' => __pl('Height'), 'post' => 1, 'req' => ['_virtual' => ''], ), ); $params['kkart_variants'] = array(// TODO: Complite 'is_variants' => array( 'type' => 'checkbox', 'label' => __pl('Is Variants'), ), 'product_variants' => array( 'type' => 'variable_porduct', 'label' => __pl('Variants'), ), ); $params['kkart_linkedprod'] = array(// TODO: fix 'upsell' => array( 'type' => 'text', 'label' => __pl('Upsell'), 'post' => 1, ), 'cross_sell' => array( 'type' => 'text', 'label' => __pl('Cross Sell'), 'post' => 1, ), ); $params['kkart_advanced'] = array( '_purchase_note' => array( 'type' => 'textarea', 'label' => __pl('Purchase Note'), 'post' => 1, ), 'menu_order' => array( // TODO: fix 'type' => 'spinner', 'label' => __pl('Menu Order'), 'post' => 1, ), 'comment_status' => array( 'type' => 'checkbox', 'label' => __pl('Enable Reviews'), 'post' => 1, ), ); $params['settings']['kkart_gallery'] = __pl('Product Gallery'); $params['settings']['kkart_pricing'] = __pl('Product pricing'); $params['settings']['kkart_inventory'] = __pl('Product Inventory'); $params['settings']['kkart_shipping'] = __pl('Product Shipping'); $params['settings']['kkart_variants'] = __pl('Variants'); $params['settings']['kkart_linkedprod'] = __pl('Linked Product'); $params['settings']['kkart_advanced'] = __pl('Advanced'); $params['post_type_cats']['product'] = array('kkart_gallery', 'kkart_pricing', 'kkart_inventory', 'kkart_shipping', 'kkart_variants', 'kkart_linkedprod', 'kkart_advanced' ); return $params; }PK! y{{class-kkart-discounts.phpnu[ Item Key => Value */ protected $discounts = array(); /** * KKART_Discounts Constructor. * * @param KKART_Cart|KKART_Order $object Cart or order object. */ public function __construct( $object = null ) { if ( is_a( $object, 'KKART_Cart' ) ) { $this->set_items_from_cart( $object ); } elseif ( is_a( $object, 'KKART_Order' ) ) { $this->set_items_from_order( $object ); } } /** * Set items directly. Used by KKART_Cart_Totals. * * @since 3.2.3 * @param array $items Items to set. */ public function set_items( $items ) { $this->items = $items; $this->discounts = array(); uasort( $this->items, array( $this, 'sort_by_price' ) ); } /** * Normalise cart items which will be discounted. * * @since 3.2.0 * @param KKART_Cart $cart Cart object. */ public function set_items_from_cart( $cart ) { $this->items = array(); $this->discounts = array(); if ( ! is_a( $cart, 'KKART_Cart' ) ) { return; } $this->object = $cart; foreach ( $cart->get_cart() as $key => $cart_item ) { $item = new stdClass(); $item->key = $key; $item->object = $cart_item; $item->product = $cart_item['data']; $item->quantity = $cart_item['quantity']; $item->price = kkart_add_number_precision_deep( $item->product->get_price() * $item->quantity ); $this->items[ $key ] = $item; } uasort( $this->items, array( $this, 'sort_by_price' ) ); } /** * Normalise order items which will be discounted. * * @since 3.2.0 * @param KKART_Order $order Order object. */ public function set_items_from_order( $order ) { $this->items = array(); $this->discounts = array(); if ( ! is_a( $order, 'KKART_Order' ) ) { return; } $this->object = $order; foreach ( $order->get_items() as $order_item ) { $item = new stdClass(); $item->key = $order_item->get_id(); $item->object = $order_item; $item->product = $order_item->get_product(); $item->quantity = $order_item->get_quantity(); $item->price = kkart_add_number_precision_deep( $order_item->get_subtotal() ); if ( $order->get_prices_include_tax() ) { $item->price += kkart_add_number_precision_deep( $order_item->get_subtotal_tax() ); } $this->items[ $order_item->get_id() ] = $item; } uasort( $this->items, array( $this, 'sort_by_price' ) ); } /** * Get the object concerned. * * @since 3.3.2 * @return object */ public function get_object() { return $this->object; } /** * Get items. * * @since 3.2.0 * @return object[] */ public function get_items() { return $this->items; } /** * Get items to validate. * * @since 3.3.2 * @return object[] */ public function get_items_to_validate() { return apply_filters( 'kkart_coupon_get_items_to_validate', $this->get_items(), $this ); } /** * Get discount by key with or without precision. * * @since 3.2.0 * @param string $key name of discount row to return. * @param bool $in_cents Should the totals be returned in cents, or without precision. * @return float */ public function get_discount( $key, $in_cents = false ) { $item_discount_totals = $this->get_discounts_by_item( $in_cents ); return isset( $item_discount_totals[ $key ] ) ? $item_discount_totals[ $key ] : 0; } /** * Get all discount totals. * * @since 3.2.0 * @param bool $in_cents Should the totals be returned in cents, or without precision. * @return array */ public function get_discounts( $in_cents = false ) { $discounts = $this->discounts; return $in_cents ? $discounts : kkart_remove_number_precision_deep( $discounts ); } /** * Get all discount totals per item. * * @since 3.2.0 * @param bool $in_cents Should the totals be returned in cents, or without precision. * @return array */ public function get_discounts_by_item( $in_cents = false ) { $discounts = $this->discounts; $item_discount_totals = (array) array_shift( $discounts ); foreach ( $discounts as $item_discounts ) { foreach ( $item_discounts as $item_key => $item_discount ) { $item_discount_totals[ $item_key ] += $item_discount; } } return $in_cents ? $item_discount_totals : kkart_remove_number_precision_deep( $item_discount_totals ); } /** * Get all discount totals per coupon. * * @since 3.2.0 * @param bool $in_cents Should the totals be returned in cents, or without precision. * @return array */ public function get_discounts_by_coupon( $in_cents = false ) { $coupon_discount_totals = array_map( 'array_sum', $this->discounts ); return $in_cents ? $coupon_discount_totals : kkart_remove_number_precision_deep( $coupon_discount_totals ); } /** * Get discounted price of an item without precision. * * @since 3.2.0 * @param object $item Get data for this item. * @return float */ public function get_discounted_price( $item ) { return kkart_remove_number_precision_deep( $this->get_discounted_price_in_cents( $item ) ); } /** * Get discounted price of an item to precision (in cents). * * @since 3.2.0 * @param object $item Get data for this item. * @return int */ public function get_discounted_price_in_cents( $item ) { return absint( NumberUtil::round( $item->price - $this->get_discount( $item->key, true ) ) ); } /** * Apply a discount to all items using a coupon. * * @since 3.2.0 * @param KKART_Coupon $coupon Coupon object being applied to the items. * @param bool $validate Set to false to skip coupon validation. * @throws Exception Error message when coupon isn't valid. * @return bool|WP_Error True if applied or WP_Error instance in failure. */ public function apply_coupon( $coupon, $validate = true ) { if ( ! is_a( $coupon, 'KKART_Coupon' ) ) { return new WP_Error( 'invalid_coupon', __( 'Invalid coupon', 'kkart' ) ); } $is_coupon_valid = $validate ? $this->is_coupon_valid( $coupon ) : true; if ( is_wp_error( $is_coupon_valid ) ) { return $is_coupon_valid; } if ( ! isset( $this->discounts[ $coupon->get_code() ] ) ) { $this->discounts[ $coupon->get_code() ] = array_fill_keys( array_keys( $this->items ), 0 ); } $items_to_apply = $this->get_items_to_apply_coupon( $coupon ); // Core discounts are handled here as of 3.2. switch ( $coupon->get_discount_type() ) { case 'percent': $this->apply_coupon_percent( $coupon, $items_to_apply ); break; case 'fixed_product': $this->apply_coupon_fixed_product( $coupon, $items_to_apply ); break; case 'fixed_cart': $this->apply_coupon_fixed_cart( $coupon, $items_to_apply ); break; default: $this->apply_coupon_custom( $coupon, $items_to_apply ); break; } return true; } /** * Sort by price. * * @since 3.2.0 * @param array $a First element. * @param array $b Second element. * @return int */ protected function sort_by_price( $a, $b ) { $price_1 = $a->price * $a->quantity; $price_2 = $b->price * $b->quantity; if ( $price_1 === $price_2 ) { return 0; } return ( $price_1 < $price_2 ) ? 1 : -1; } /** * Filter out all products which have been fully discounted to 0. * Used as array_filter callback. * * @since 3.2.0 * @param object $item Get data for this item. * @return bool */ protected function filter_products_with_price( $item ) { return $this->get_discounted_price_in_cents( $item ) > 0; } /** * Get items which the coupon should be applied to. * * @since 3.2.0 * @param object $coupon Coupon object. * @return array */ protected function get_items_to_apply_coupon( $coupon ) { $items_to_apply = array(); foreach ( $this->get_items_to_validate() as $item ) { $item_to_apply = clone $item; // Clone the item so changes to this item do not affect the originals. if ( 0 === $this->get_discounted_price_in_cents( $item_to_apply ) || 0 >= $item_to_apply->quantity ) { continue; } if ( ! $coupon->is_valid_for_product( $item_to_apply->product, $item_to_apply->object ) && ! $coupon->is_valid_for_cart() ) { continue; } $items_to_apply[] = $item_to_apply; } return $items_to_apply; } /** * Apply percent discount to items and return an array of discounts granted. * * @since 3.2.0 * @param KKART_Coupon $coupon Coupon object. Passed through filters. * @param array $items_to_apply Array of items to apply the coupon to. * @return int Total discounted. */ protected function apply_coupon_percent( $coupon, $items_to_apply ) { $total_discount = 0; $cart_total = 0; $limit_usage_qty = 0; $applied_count = 0; $adjust_final_discount = true; if ( null !== $coupon->get_limit_usage_to_x_items() ) { $limit_usage_qty = $coupon->get_limit_usage_to_x_items(); } $coupon_amount = $coupon->get_amount(); foreach ( $items_to_apply as $item ) { // Find out how much price is available to discount for the item. $discounted_price = $this->get_discounted_price_in_cents( $item ); // Get the price we actually want to discount, based on settings. $price_to_discount = ( 'yes' === get_option( 'kkart_calc_discounts_sequentially', 'no' ) ) ? $discounted_price : NumberUtil::round( $item->price ); // See how many and what price to apply to. $apply_quantity = $limit_usage_qty && ( $limit_usage_qty - $applied_count ) < $item->quantity ? $limit_usage_qty - $applied_count : $item->quantity; $apply_quantity = max( 0, apply_filters( 'kkart_coupon_get_apply_quantity', $apply_quantity, $item, $coupon, $this ) ); $price_to_discount = ( $price_to_discount / $item->quantity ) * $apply_quantity; // Run coupon calculations. $discount = floor( $price_to_discount * ( $coupon_amount / 100 ) ); if ( is_a( $this->object, 'KKART_Cart' ) && has_filter( 'kkart_coupon_get_discount_amount' ) ) { // Send through the legacy filter, but not as cents. $filtered_discount = kkart_add_number_precision( apply_filters( 'kkart_coupon_get_discount_amount', kkart_remove_number_precision( $discount ), kkart_remove_number_precision( $price_to_discount ), $item->object, false, $coupon ) ); if ( $filtered_discount !== $discount ) { $discount = $filtered_discount; $adjust_final_discount = false; } } $discount = kkart_round_discount( min( $discounted_price, $discount ), 0 ); $cart_total = $cart_total + $price_to_discount; $total_discount = $total_discount + $discount; $applied_count = $applied_count + $apply_quantity; // Store code and discount amount per item. $this->discounts[ $coupon->get_code() ][ $item->key ] += $discount; } // Work out how much discount would have been given to the cart as a whole and compare to what was discounted on all line items. $cart_total_discount = kkart_round_discount( $cart_total * ( $coupon_amount / 100 ), 0 ); if ( $total_discount < $cart_total_discount && $adjust_final_discount ) { $total_discount += $this->apply_coupon_remainder( $coupon, $items_to_apply, $cart_total_discount - $total_discount ); } return $total_discount; } /** * Apply fixed product discount to items. * * @since 3.2.0 * @param KKART_Coupon $coupon Coupon object. Passed through filters. * @param array $items_to_apply Array of items to apply the coupon to. * @param int $amount Fixed discount amount to apply in cents. Leave blank to pull from coupon. * @return int Total discounted. */ protected function apply_coupon_fixed_product( $coupon, $items_to_apply, $amount = null ) { $total_discount = 0; $amount = $amount ? $amount : kkart_add_number_precision( $coupon->get_amount() ); $limit_usage_qty = 0; $applied_count = 0; if ( null !== $coupon->get_limit_usage_to_x_items() ) { $limit_usage_qty = $coupon->get_limit_usage_to_x_items(); } foreach ( $items_to_apply as $item ) { // Find out how much price is available to discount for the item. $discounted_price = $this->get_discounted_price_in_cents( $item ); // Get the price we actually want to discount, based on settings. $price_to_discount = ( 'yes' === get_option( 'kkart_calc_discounts_sequentially', 'no' ) ) ? $discounted_price : $item->price; // Run coupon calculations. if ( $limit_usage_qty ) { $apply_quantity = $limit_usage_qty - $applied_count < $item->quantity ? $limit_usage_qty - $applied_count : $item->quantity; $apply_quantity = max( 0, apply_filters( 'kkart_coupon_get_apply_quantity', $apply_quantity, $item, $coupon, $this ) ); $discount = min( $amount, $item->price / $item->quantity ) * $apply_quantity; } else { $apply_quantity = apply_filters( 'kkart_coupon_get_apply_quantity', $item->quantity, $item, $coupon, $this ); $discount = $amount * $apply_quantity; } if ( is_a( $this->object, 'KKART_Cart' ) && has_filter( 'kkart_coupon_get_discount_amount' ) ) { // Send through the legacy filter, but not as cents. $discount = kkart_add_number_precision( apply_filters( 'kkart_coupon_get_discount_amount', kkart_remove_number_precision( $discount ), kkart_remove_number_precision( $price_to_discount ), $item->object, false, $coupon ) ); } $discount = min( $discounted_price, $discount ); $total_discount = $total_discount + $discount; $applied_count = $applied_count + $apply_quantity; // Store code and discount amount per item. $this->discounts[ $coupon->get_code() ][ $item->key ] += $discount; } return $total_discount; } /** * Apply fixed cart discount to items. * * @since 3.2.0 * @param KKART_Coupon $coupon Coupon object. Passed through filters. * @param array $items_to_apply Array of items to apply the coupon to. * @param int $amount Fixed discount amount to apply in cents. Leave blank to pull from coupon. * @return int Total discounted. */ protected function apply_coupon_fixed_cart( $coupon, $items_to_apply, $amount = null ) { $total_discount = 0; $amount = $amount ? $amount : kkart_add_number_precision( $coupon->get_amount() ); $items_to_apply = array_filter( $items_to_apply, array( $this, 'filter_products_with_price' ) ); $item_count = array_sum( wp_list_pluck( $items_to_apply, 'quantity' ) ); if ( ! $item_count ) { return $total_discount; } if ( ! $amount ) { // If there is no amount we still send it through so filters are fired. $total_discount = $this->apply_coupon_fixed_product( $coupon, $items_to_apply, 0 ); } else { $per_item_discount = absint( $amount / $item_count ); // round it down to the nearest cent. if ( $per_item_discount > 0 ) { $total_discount = $this->apply_coupon_fixed_product( $coupon, $items_to_apply, $per_item_discount ); /** * If there is still discount remaining, repeat the process. */ if ( $total_discount > 0 && $total_discount < $amount ) { $total_discount += $this->apply_coupon_fixed_cart( $coupon, $items_to_apply, $amount - $total_discount ); } } elseif ( $amount > 0 ) { $total_discount += $this->apply_coupon_remainder( $coupon, $items_to_apply, $amount ); } } return $total_discount; } /** * Apply custom coupon discount to items. * * @since 3.3 * @param KKART_Coupon $coupon Coupon object. Passed through filters. * @param array $items_to_apply Array of items to apply the coupon to. * @return int Total discounted. */ protected function apply_coupon_custom( $coupon, $items_to_apply ) { $limit_usage_qty = 0; $applied_count = 0; if ( null !== $coupon->get_limit_usage_to_x_items() ) { $limit_usage_qty = $coupon->get_limit_usage_to_x_items(); } // Apply the coupon to each item. foreach ( $items_to_apply as $item ) { // Find out how much price is available to discount for the item. $discounted_price = $this->get_discounted_price_in_cents( $item ); // Get the price we actually want to discount, based on settings. $price_to_discount = kkart_remove_number_precision( ( 'yes' === get_option( 'kkart_calc_discounts_sequentially', 'no' ) ) ? $discounted_price : $item->price ); // See how many and what price to apply to. $apply_quantity = $limit_usage_qty && ( $limit_usage_qty - $applied_count ) < $item->quantity ? $limit_usage_qty - $applied_count : $item->quantity; $apply_quantity = max( 0, apply_filters( 'kkart_coupon_get_apply_quantity', $apply_quantity, $item, $coupon, $this ) ); // Run coupon calculations. $discount = kkart_add_number_precision( $coupon->get_discount_amount( $price_to_discount / $item->quantity, $item->object, true ) ) * $apply_quantity; $discount = kkart_round_discount( min( $discounted_price, $discount ), 0 ); $applied_count = $applied_count + $apply_quantity; // Store code and discount amount per item. $this->discounts[ $coupon->get_code() ][ $item->key ] += $discount; } // Allow post-processing for custom coupon types (e.g. calculating discrepancy, etc). $this->discounts[ $coupon->get_code() ] = apply_filters( 'kkart_coupon_custom_discounts_array', $this->discounts[ $coupon->get_code() ], $coupon ); return array_sum( $this->discounts[ $coupon->get_code() ] ); } /** * Deal with remaining fractional discounts by splitting it over items * until the amount is expired, discounting 1 cent at a time. * * @since 3.2.0 * @param KKART_Coupon $coupon Coupon object if appliable. Passed through filters. * @param array $items_to_apply Array of items to apply the coupon to. * @param int $amount Fixed discount amount to apply. * @return int Total discounted. */ protected function apply_coupon_remainder( $coupon, $items_to_apply, $amount ) { $total_discount = 0; foreach ( $items_to_apply as $item ) { for ( $i = 0; $i < $item->quantity; $i ++ ) { // Find out how much price is available to discount for the item. $price_to_discount = $this->get_discounted_price_in_cents( $item ); // Run coupon calculations. $discount = min( $price_to_discount, 1 ); // Store totals. $total_discount += $discount; // Store code and discount amount per item. $this->discounts[ $coupon->get_code() ][ $item->key ] += $discount; if ( $total_discount >= $amount ) { break 2; } } if ( $total_discount >= $amount ) { break; } } return $total_discount; } /** * Ensure coupon exists or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_exists( $coupon ) { if ( ! $coupon->get_id() && ! $coupon->get_virtual() ) { /* translators: %s: coupon code */ throw new Exception( sprintf( __( 'Coupon "%s" does not exist!', 'kkart' ), esc_html( $coupon->get_code() ) ), 105 ); } return true; } /** * Ensure coupon usage limit is valid or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_usage_limit( $coupon ) { if ( $coupon->get_usage_limit() > 0 && $coupon->get_usage_count() >= $coupon->get_usage_limit() ) { throw new Exception( __( 'Coupon usage limit has been reached.', 'kkart' ), 106 ); } return true; } /** * Ensure coupon user usage limit is valid or throw exception. * * Per user usage limit - check here if user is logged in (against user IDs). * Checked again for emails later on in KKART_Cart::check_customer_coupons(). * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @param int $user_id User ID. * @return bool */ protected function validate_coupon_user_usage_limit( $coupon, $user_id = 0 ) { if ( empty( $user_id ) ) { if ( $this->object instanceof KKART_Order ) { $user_id = $this->object->get_customer_id(); } else { $user_id = get_current_user_id(); } } if ( $coupon && $user_id && apply_filters( 'kkart_coupon_validate_user_usage_limit', $coupon->get_usage_limit_per_user() > 0, $user_id, $coupon, $this ) && $coupon->get_id() && $coupon->get_data_store() ) { $data_store = $coupon->get_data_store(); $usage_count = $data_store->get_usage_by_user_id( $coupon, $user_id ); if ( $usage_count >= $coupon->get_usage_limit_per_user() ) { throw new Exception( __( 'Coupon usage limit has been reached.', 'kkart' ), 106 ); } } return true; } /** * Ensure coupon date is valid or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_expiry_date( $coupon ) { if ( $coupon->get_date_expires() && apply_filters( 'kkart_coupon_validate_expiry_date', time() > $coupon->get_date_expires()->getTimestamp(), $coupon, $this ) ) { throw new Exception( __( 'This coupon has expired.', 'kkart' ), 107 ); } return true; } /** * Ensure coupon amount is valid or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_minimum_amount( $coupon ) { $subtotal = kkart_remove_number_precision( $this->get_object_subtotal() ); if ( $coupon->get_minimum_amount() > 0 && apply_filters( 'kkart_coupon_validate_minimum_amount', $coupon->get_minimum_amount() > $subtotal, $coupon, $subtotal ) ) { /* translators: %s: coupon minimum amount */ throw new Exception( sprintf( __( 'The minimum spend for this coupon is %s.', 'kkart' ), kkart_price( $coupon->get_minimum_amount() ) ), 108 ); } return true; } /** * Ensure coupon amount is valid or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_maximum_amount( $coupon ) { $subtotal = kkart_remove_number_precision( $this->get_object_subtotal() ); if ( $coupon->get_maximum_amount() > 0 && apply_filters( 'kkart_coupon_validate_maximum_amount', $coupon->get_maximum_amount() < $subtotal, $coupon ) ) { /* translators: %s: coupon maximum amount */ throw new Exception( sprintf( __( 'The maximum spend for this coupon is %s.', 'kkart' ), kkart_price( $coupon->get_maximum_amount() ) ), 112 ); } return true; } /** * Ensure coupon is valid for products in the list is valid or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_product_ids( $coupon ) { if ( count( $coupon->get_product_ids() ) > 0 ) { $valid = false; foreach ( $this->get_items_to_validate() as $item ) { if ( $item->product && in_array( $item->product->get_id(), $coupon->get_product_ids(), true ) || in_array( $item->product->get_parent_id(), $coupon->get_product_ids(), true ) ) { $valid = true; break; } } if ( ! $valid ) { throw new Exception( __( 'Sorry, this coupon is not applicable to selected products.', 'kkart' ), 109 ); } } return true; } /** * Ensure coupon is valid for product categories in the list is valid or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_product_categories( $coupon ) { if ( count( $coupon->get_product_categories() ) > 0 ) { $valid = false; foreach ( $this->get_items_to_validate() as $item ) { if ( $coupon->get_exclude_sale_items() && $item->product && $item->product->is_on_sale() ) { continue; } $product_cats = kkart_get_product_cat_ids( $item->product->get_id() ); if ( $item->product->get_parent_id() ) { $product_cats = array_merge( $product_cats, kkart_get_product_cat_ids( $item->product->get_parent_id() ) ); } // If we find an item with a cat in our allowed cat list, the coupon is valid. if ( count( array_intersect( $product_cats, $coupon->get_product_categories() ) ) > 0 ) { $valid = true; break; } } if ( ! $valid ) { throw new Exception( __( 'Sorry, this coupon is not applicable to selected products.', 'kkart' ), 109 ); } } return true; } /** * Ensure coupon is valid for sale items in the list is valid or throw exception. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_sale_items( $coupon ) { if ( $coupon->get_exclude_sale_items() ) { $valid = true; foreach ( $this->get_items_to_validate() as $item ) { if ( $item->product && $item->product->is_on_sale() ) { $valid = false; break; } } if ( ! $valid ) { throw new Exception( __( 'Sorry, this coupon is not valid for sale items.', 'kkart' ), 110 ); } } return true; } /** * All exclusion rules must pass at the same time for a product coupon to be valid. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_excluded_items( $coupon ) { $items = $this->get_items_to_validate(); if ( ! empty( $items ) && $coupon->is_type( kkart_get_product_coupon_types() ) ) { $valid = false; foreach ( $items as $item ) { if ( $item->product && $coupon->is_valid_for_product( $item->product, $item->object ) ) { $valid = true; break; } } if ( ! $valid ) { throw new Exception( __( 'Sorry, this coupon is not applicable to selected products.', 'kkart' ), 109 ); } } return true; } /** * Cart discounts cannot be added if non-eligible product is found. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_eligible_items( $coupon ) { if ( ! $coupon->is_type( kkart_get_product_coupon_types() ) ) { $this->validate_coupon_sale_items( $coupon ); $this->validate_coupon_excluded_product_ids( $coupon ); $this->validate_coupon_excluded_product_categories( $coupon ); } return true; } /** * Exclude products. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_excluded_product_ids( $coupon ) { // Exclude Products. if ( count( $coupon->get_excluded_product_ids() ) > 0 ) { $products = array(); foreach ( $this->get_items_to_validate() as $item ) { if ( $item->product && in_array( $item->product->get_id(), $coupon->get_excluded_product_ids(), true ) || in_array( $item->product->get_parent_id(), $coupon->get_excluded_product_ids(), true ) ) { $products[] = $item->product->get_name(); } } if ( ! empty( $products ) ) { /* translators: %s: products list */ throw new Exception( sprintf( __( 'Sorry, this coupon is not applicable to the products: %s.', 'kkart' ), implode( ', ', $products ) ), 113 ); } } return true; } /** * Exclude categories from product list. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool */ protected function validate_coupon_excluded_product_categories( $coupon ) { if ( count( $coupon->get_excluded_product_categories() ) > 0 ) { $categories = array(); foreach ( $this->get_items_to_validate() as $item ) { if ( ! $item->product ) { continue; } $product_cats = kkart_get_product_cat_ids( $item->product->get_id() ); if ( $item->product->get_parent_id() ) { $product_cats = array_merge( $product_cats, kkart_get_product_cat_ids( $item->product->get_parent_id() ) ); } $cat_id_list = array_intersect( $product_cats, $coupon->get_excluded_product_categories() ); if ( count( $cat_id_list ) > 0 ) { foreach ( $cat_id_list as $cat_id ) { $cat = get_term( $cat_id, 'product_cat' ); $categories[] = $cat->name; } } } if ( ! empty( $categories ) ) { /* translators: %s: categories list */ throw new Exception( sprintf( __( 'Sorry, this coupon is not applicable to the categories: %s.', 'kkart' ), implode( ', ', array_unique( $categories ) ) ), 114 ); } } return true; } /** * Get the object subtotal * * @return int */ protected function get_object_subtotal() { if ( is_a( $this->object, 'KKART_Cart' ) ) { return kkart_add_number_precision( $this->object->get_displayed_subtotal() ); } elseif ( is_a( $this->object, 'KKART_Order' ) ) { $subtotal = kkart_add_number_precision( $this->object->get_subtotal() ); if ( $this->object->get_prices_include_tax() ) { // Add tax to tax-exclusive subtotal. $subtotal = $subtotal + kkart_add_number_precision( NumberUtil::round( $this->object->get_total_tax(), kkart_get_price_decimals() ) ); } return $subtotal; } else { return array_sum( wp_list_pluck( $this->items, 'price' ) ); } } /** * Check if a coupon is valid. * * Error Codes: * - 100: Invalid filtered. * - 101: Invalid removed. * - 102: Not yours removed. * - 103: Already applied. * - 104: Individual use only. * - 105: Not exists. * - 106: Usage limit reached. * - 107: Expired. * - 108: Minimum spend limit not met. * - 109: Not applicable. * - 110: Not valid for sale items. * - 111: Missing coupon code. * - 112: Maximum spend limit met. * - 113: Excluded products. * - 114: Excluded categories. * * @since 3.2.0 * @throws Exception Error message. * @param KKART_Coupon $coupon Coupon data. * @return bool|WP_Error */ public function is_coupon_valid( $coupon ) { try { $this->validate_coupon_exists( $coupon ); $this->validate_coupon_usage_limit( $coupon ); $this->validate_coupon_user_usage_limit( $coupon ); $this->validate_coupon_expiry_date( $coupon ); $this->validate_coupon_minimum_amount( $coupon ); $this->validate_coupon_maximum_amount( $coupon ); $this->validate_coupon_product_ids( $coupon ); $this->validate_coupon_product_categories( $coupon ); $this->validate_coupon_excluded_items( $coupon ); $this->validate_coupon_eligible_items( $coupon ); if ( ! apply_filters( 'kkart_coupon_is_valid', true, $coupon, $this ) ) { throw new Exception( __( 'Coupon is not valid.', 'kkart' ), 100 ); } } catch ( Exception $e ) { /** * Filter the coupon error message. * * @param string $error_message Error message. * @param int $error_code Error code. * @param KKART_Coupon $coupon Coupon data. */ $message = apply_filters( 'kkart_coupon_error', is_numeric( $e->getMessage() ) ? $coupon->get_coupon_error( $e->getMessage() ) : $e->getMessage(), $e->getCode(), $coupon ); return new WP_Error( 'invalid_coupon', $message, array( 'status' => 400, ) ); } return true; } } PK!لHE*E*class-kkart-session-handler.phpnu[_cookie = apply_filters( 'kkart_cookie', 'wp_kkart_session_' . COOKIEHASH ); $this->_table = $GLOBALS['wpdb']->prefix . 'kkart_sessions'; } /** * Init hooks and session data. * * @since 3.3.0 */ public function init() { $this->init_session_cookie(); add_action( 'kkart_set_cart_cookies', array( $this, 'set_customer_session_cookie' ), 10 ); add_action( 'shutdown', array( $this, 'save_data' ), 20 ); add_action( 'wp_logout', array( $this, 'destroy_session' ) ); if ( ! is_user_logged_in() ) { add_filter( 'nonce_user_logged_out', array( $this, 'nonce_user_logged_out' ) ); } } /** * Setup cookie and customer ID. * * @since 3.6.0 */ public function init_session_cookie() { $cookie = $this->get_session_cookie(); if ( $cookie ) { $this->_customer_id = $cookie[0]; $this->_session_expiration = $cookie[1]; $this->_session_expiring = $cookie[2]; $this->_has_cookie = true; $this->_data = $this->get_session_data(); // If the user logs in, update session. if ( is_user_logged_in() && strval( get_current_user_id() ) !== $this->_customer_id ) { $guest_session_id = $this->_customer_id; $this->_customer_id = strval( get_current_user_id() ); $this->_dirty = true; $this->save_data( $guest_session_id ); $this->set_customer_session_cookie( true ); } // Update session if its close to expiring. if ( time() > $this->_session_expiring ) { $this->set_session_expiration(); $this->update_session_timestamp( $this->_customer_id, $this->_session_expiration ); } } else { $this->set_session_expiration(); $this->_customer_id = $this->generate_customer_id(); $this->_data = $this->get_session_data(); } } /** * Sets the session cookie on-demand (usually after adding an item to the cart). * * Since the cookie name (as of 2.1) is prepended with wp, cache systems like batcache will not cache pages when set. * * Warning: Cookies will only be set if this is called before the headers are sent. * * @param bool $set Should the session cookie be set. */ public function set_customer_session_cookie( $set ) { if ( $set ) { $to_hash = $this->_customer_id . '|' . $this->_session_expiration; $cookie_hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) ); $cookie_value = $this->_customer_id . '||' . $this->_session_expiration . '||' . $this->_session_expiring . '||' . $cookie_hash; $this->_has_cookie = true; if ( ! isset( $_COOKIE[ $this->_cookie ] ) || $_COOKIE[ $this->_cookie ] !== $cookie_value ) { kkart_setcookie( $this->_cookie, $cookie_value, $this->_session_expiration, $this->use_secure_cookie(), true ); } } } /** * Should the session cookie be secure? * * @since 3.6.0 * @return bool */ protected function use_secure_cookie() { return apply_filters( 'kkart_session_use_secure_cookie', kkart_site_is_https() && is_ssl() ); } /** * Return true if the current user has an active session, i.e. a cookie to retrieve values. * * @return bool */ public function has_session() { return isset( $_COOKIE[ $this->_cookie ] ) || $this->_has_cookie || is_user_logged_in(); // @codingStandardsIgnoreLine. } /** * Set session expiration. */ public function set_session_expiration() { $this->_session_expiring = time() + intval( apply_filters( 'kkart_session_expiring', 60 * 60 * 47 ) ); // 47 Hours. $this->_session_expiration = time() + intval( apply_filters( 'kkart_session_expiration', 60 * 60 * 48 ) ); // 48 Hours. } /** * Generate a unique customer ID for guests, or return user ID if logged in. * * Uses Portable PHP password hashing framework to generate a unique cryptographically strong ID. * * @return string */ public function generate_customer_id() { $customer_id = ''; if ( is_user_logged_in() ) { $customer_id = strval( get_current_user_id() ); } if ( empty( $customer_id ) ) { $lib = ABSPATH . 'site-inc/class-phpass.php'; $lib = file_exists($lib) ? $lib : ABSPATH . 'wp-includes/class-phpass.php'; require_once($lib); $hasher = new PasswordHash( 8, false ); $customer_id = md5( $hasher->get_random_bytes( 32 ) ); } return $customer_id; } /** * Get the session cookie, if set. Otherwise return false. * * Session cookies without a customer ID are invalid. * * @return bool|array */ public function get_session_cookie() { $cookie_value = isset( $_COOKIE[ $this->_cookie ] ) ? wp_unslash( $_COOKIE[ $this->_cookie ] ) : false; // @codingStandardsIgnoreLine. if ( empty( $cookie_value ) || ! is_string( $cookie_value ) ) { return false; } list( $customer_id, $session_expiration, $session_expiring, $cookie_hash ) = explode( '||', $cookie_value ); if ( empty( $customer_id ) ) { return false; } // Validate hash. $to_hash = $customer_id . '|' . $session_expiration; $hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) ); if ( empty( $cookie_hash ) || ! hash_equals( $hash, $cookie_hash ) ) { return false; } return array( $customer_id, $session_expiration, $session_expiring, $cookie_hash ); } /** * Get session data. * * @return array */ public function get_session_data() { return $this->has_session() ? (array) $this->get_session( $this->_customer_id, array() ) : array(); } /** * Gets a cache prefix. This is used in session names so the entire cache can be invalidated with 1 function call. * * @return string */ private function get_cache_prefix() { return KKART_Cache_Helper::get_cache_prefix( KKART_SESSION_CACHE_GROUP ); } /** * Save data and delete guest session. * * @param int $old_session_key session ID before user logs in. */ public function save_data( $old_session_key = 0 ) { // Dirty if something changed - prevents saving nothing new. if ( $this->_dirty && $this->has_session() ) { global $wpdb; $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->prefix}kkart_sessions (`session_key`, `session_value`, `session_expiry`) VALUES (%s, %s, %d) ON DUPLICATE KEY UPDATE `session_value` = VALUES(`session_value`), `session_expiry` = VALUES(`session_expiry`)", $this->_customer_id, maybe_serialize( $this->_data ), $this->_session_expiration ) ); wp_cache_set( $this->get_cache_prefix() . $this->_customer_id, $this->_data, KKART_SESSION_CACHE_GROUP, $this->_session_expiration - time() ); $this->_dirty = false; if ( get_current_user_id() != $old_session_key && ! is_object( get_user_by( 'id', $old_session_key ) ) ) { $this->delete_session( $old_session_key ); } } } /** * Destroy all session data. */ public function destroy_session() { $this->delete_session( $this->_customer_id ); $this->forget_session(); } /** * Forget all session data without destroying it. */ public function forget_session() { kkart_setcookie( $this->_cookie, '', time() - YEAR_IN_SECONDS, $this->use_secure_cookie(), true ); kkart_empty_cart(); $this->_data = array(); $this->_dirty = false; $this->_customer_id = $this->generate_customer_id(); } /** * When a user is logged out, ensure they have a unique nonce by using the customer/session ID. * * @param int $uid User ID. * @return string */ public function nonce_user_logged_out( $uid ) { return $this->has_session() && $this->_customer_id ? $this->_customer_id : $uid; } /** * Cleanup session data from the database and clear caches. */ public function cleanup_sessions() { global $wpdb; $wpdb->query( $wpdb->prepare( "DELETE FROM $this->_table WHERE session_expiry < %d", time() ) ); // @codingStandardsIgnoreLine. if ( class_exists( 'KKART_Cache_Helper' ) ) { KKART_Cache_Helper::invalidate_cache_group( KKART_SESSION_CACHE_GROUP ); } } /** * Returns the session. * * @param string $customer_id Custo ID. * @param mixed $default Default session value. * @return string|array */ public function get_session( $customer_id, $default = false ) { global $wpdb; if ( Constants::is_defined( 'WP_SETUP_CONFIG' ) ) { return false; } // Try to get it from the cache, it will return false if not present or if object cache not in use. $value = wp_cache_get( $this->get_cache_prefix() . $customer_id, KKART_SESSION_CACHE_GROUP ); if ( false === $value ) { $value = $wpdb->get_var( $wpdb->prepare( "SELECT session_value FROM $this->_table WHERE session_key = %s", $customer_id ) ); // @codingStandardsIgnoreLine. if ( is_null( $value ) ) { $value = $default; } $cache_duration = $this->_session_expiration - time(); if ( 0 < $cache_duration ) { wp_cache_add( $this->get_cache_prefix() . $customer_id, $value, KKART_SESSION_CACHE_GROUP, $cache_duration ); } } return maybe_unserialize( $value ); } /** * Delete the session from the cache and database. * * @param int $customer_id Customer ID. */ public function delete_session( $customer_id ) { global $wpdb; wp_cache_delete( $this->get_cache_prefix() . $customer_id, KKART_SESSION_CACHE_GROUP ); $wpdb->delete( $this->_table, array( 'session_key' => $customer_id, ) ); } /** * Update the session expiry timestamp. * * @param string $customer_id Customer ID. * @param int $timestamp Timestamp to expire the cookie. */ public function update_session_timestamp( $customer_id, $timestamp ) { global $wpdb; $wpdb->update( $this->_table, array( 'session_expiry' => $timestamp, ), array( 'session_key' => $customer_id, ), array( '%d', ) ); } } PK!tȌ!class-kkart-product-attribute.phpnu[ 0, 'name' => '', 'options' => array(), 'position' => 0, 'visible' => false, 'variation' => false, ); /** * Return if this attribute is a taxonomy. * * @return boolean */ public function is_taxonomy() { return 0 < $this->get_id(); } /** * Get taxonomy name if applicable. * * @return string */ public function get_taxonomy() { return $this->is_taxonomy() ? $this->get_name() : ''; } /** * Get taxonomy object. * * @return array|null */ public function get_taxonomy_object() { global $kkart_product_attributes; return $this->is_taxonomy() ? $kkart_product_attributes[ $this->get_name() ] : null; } /** * Gets terms from the stored options. * * @return array|null */ public function get_terms() { if ( ! $this->is_taxonomy() || ! taxonomy_exists( $this->get_name() ) ) { return null; } $terms = array(); foreach ( $this->get_options() as $option ) { if ( is_int( $option ) ) { $term = get_term_by( 'id', $option, $this->get_name() ); } else { // Term names get escaped in WP. See sanitize_term_field. $term = get_term_by( 'name', $option, $this->get_name() ); if ( ! $term || is_wp_error( $term ) ) { $new_term = wp_insert_term( $option, $this->get_name() ); $term = is_wp_error( $new_term ) ? false : get_term_by( 'id', $new_term['term_id'], $this->get_name() ); } } if ( $term && ! is_wp_error( $term ) ) { $terms[] = $term; } } return $terms; } /** * Gets slugs from the stored options, or just the string if text based. * * @return array */ public function get_slugs() { if ( ! $this->is_taxonomy() || ! taxonomy_exists( $this->get_name() ) ) { return $this->get_options(); } $terms = array(); foreach ( $this->get_options() as $option ) { if ( is_int( $option ) ) { $term = get_term_by( 'id', $option, $this->get_name() ); } else { $term = get_term_by( 'name', $option, $this->get_name() ); if ( ! $term || is_wp_error( $term ) ) { $new_term = wp_insert_term( $option, $this->get_name() ); $term = is_wp_error( $new_term ) ? false : get_term_by( 'id', $new_term['term_id'], $this->get_name() ); } } if ( $term && ! is_wp_error( $term ) ) { $terms[] = $term->slug; } } return $terms; } /** * Returns all data for this object. * * @return array */ public function get_data() { return array_merge( $this->data, array( 'is_visible' => $this->get_visible() ? 1 : 0, 'is_variation' => $this->get_variation() ? 1 : 0, 'is_taxonomy' => $this->is_taxonomy() ? 1 : 0, 'value' => $this->is_taxonomy() ? '' : kkart_implode_text_attributes( $this->get_options() ), ) ); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- */ /** * Set ID (this is the attribute ID). * * @param int $value Attribute ID. */ public function set_id( $value ) { $this->data['id'] = absint( $value ); } /** * Set name (this is the attribute name or taxonomy). * * @param int $value Attribute name. */ public function set_name( $value ) { $this->data['name'] = $value; } /** * Set options. * * @param array $value Attribute options. */ public function set_options( $value ) { $this->data['options'] = $value; } /** * Set position. * * @param int $value Attribute position. */ public function set_position( $value ) { $this->data['position'] = absint( $value ); } /** * Set if visible. * * @param bool $value If is visible on Product's additional info tab. */ public function set_visible( $value ) { $this->data['visible'] = kkart_string_to_bool( $value ); } /** * Set if variation. * * @param bool $value If is used for variations. */ public function set_variation( $value ) { $this->data['variation'] = kkart_string_to_bool( $value ); } /* |-------------------------------------------------------------------------- | Getters |-------------------------------------------------------------------------- */ /** * Get the ID. * * @return int */ public function get_id() { return $this->data['id']; } /** * Get name. * * @return string */ public function get_name() { return $this->data['name']; } /** * Get options. * * @return array */ public function get_options() { return $this->data['options']; } /** * Get position. * * @return int */ public function get_position() { return $this->data['position']; } /** * Get if visible. * * @return bool */ public function get_visible() { return $this->data['visible']; } /** * Get if variation. * * @return bool */ public function get_variation() { return $this->data['variation']; } /* |-------------------------------------------------------------------------- | ArrayAccess/Backwards compatibility. |-------------------------------------------------------------------------- */ /** * OffsetGet. * * @param string $offset Offset. * @return mixed */ public function offsetGet( $offset ) { switch ( $offset ) { case 'is_variation': return $this->get_variation() ? 1 : 0; case 'is_visible': return $this->get_visible() ? 1 : 0; case 'is_taxonomy': return $this->is_taxonomy() ? 1 : 0; case 'value': return $this->is_taxonomy() ? '' : kkart_implode_text_attributes( $this->get_options() ); default: if ( is_callable( array( $this, "get_$offset" ) ) ) { return $this->{"get_$offset"}(); } break; } return ''; } /** * OffsetSet. * * @param string $offset Offset. * @param mixed $value Value. */ public function offsetSet( $offset, $value ) { switch ( $offset ) { case 'is_variation': $this->set_variation( $value ); break; case 'is_visible': $this->set_visible( $value ); break; case 'value': $this->set_options( $value ); break; default: if ( is_callable( array( $this, "set_$offset" ) ) ) { return $this->{"set_$offset"}( $value ); } break; } } /** * OffsetUnset. * * @param string $offset Offset. */ public function offsetUnset( $offset ) {} /** * OffsetExists. * * @param string $offset Offset. * @return bool */ public function offsetExists( $offset ) { return in_array( $offset, array_merge( array( 'is_variation', 'is_visible', 'is_taxonomy', 'value' ), array_keys( $this->data ) ), true ); } } PK!fyyclass-kkart-query.phpnu[init_query_vars(); } /** * Get any errors from querystring. */ public function get_errors() { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $error = ! empty( $_GET['kkart_error'] ) ? sanitize_text_field( wp_unslash( $_GET['kkart_error'] ) ) : ''; if ( $error && ! kkart_has_notice( $error, 'error' ) ) { kkart_add_notice( $error, 'error' ); } } /** * Init query vars by loading options. */ public function init_query_vars() { // Query vars to add to WP. $this->query_vars = array( // Checkout actions. 'order-pay' => get_option( 'kkart_checkout_pay_endpoint', 'order-pay' ), 'order-received' => get_option( 'kkart_checkout_order_received_endpoint', 'order-received' ), // My account actions. 'orders' => get_option( 'kkart_myaccount_orders_endpoint', 'orders' ), 'view-order' => get_option( 'kkart_myaccount_view_order_endpoint', 'view-order' ), 'downloads' => get_option( 'kkart_myaccount_downloads_endpoint', 'downloads' ), 'edit-account' => get_option( 'kkart_myaccount_edit_account_endpoint', 'edit-account' ), 'edit-address' => get_option( 'kkart_myaccount_edit_address_endpoint', 'edit-address' ), 'payment-methods' => get_option( 'kkart_myaccount_payment_methods_endpoint', 'payment-methods' ), 'lost-password' => get_option( 'kkart_myaccount_lost_password_endpoint', 'lost-password' ), 'customer-logout' => get_option( 'kkart_logout_endpoint', 'customer-logout' ), 'add-payment-method' => get_option( 'kkart_myaccount_add_payment_method_endpoint', 'add-payment-method' ), 'delete-payment-method' => get_option( 'kkart_myaccount_delete_payment_method_endpoint', 'delete-payment-method' ), 'set-default-payment-method' => get_option( 'kkart_myaccount_set_default_payment_method_endpoint', 'set-default-payment-method' ), ); } /** * Get page title for an endpoint. * * @param string $endpoint Endpoint key. * @param string $action Optional action or variation within the endpoint. * * @since 2.3.0 * @since 4.6.0 Added $action parameter. * @return string The page title. */ public function get_endpoint_title( $endpoint, $action = '' ) { global $wp; switch ( $endpoint ) { case 'order-pay': $title = __( 'Pay for order', 'kkart' ); break; case 'order-received': $title = __( 'Order received', 'kkart' ); break; case 'orders': if ( ! empty( $wp->query_vars['orders'] ) ) { /* translators: %s: page */ $title = sprintf( __( 'Orders (page %d)', 'kkart' ), intval( $wp->query_vars['orders'] ) ); } else { $title = __( 'Orders', 'kkart' ); } break; case 'view-order': $order = kkart_get_order( $wp->query_vars['view-order'] ); /* translators: %s: order number */ $title = ( $order ) ? sprintf( __( 'Order #%s', 'kkart' ), $order->get_order_number() ) : ''; break; case 'downloads': $title = __( 'Downloads', 'kkart' ); break; case 'edit-account': $title = __( 'Account details', 'kkart' ); break; case 'edit-address': $title = __( 'Addresses', 'kkart' ); break; case 'payment-methods': $title = __( 'Payment methods', 'kkart' ); break; case 'add-payment-method': $title = __( 'Add payment method', 'kkart' ); break; case 'lost-password': if ( in_array( $action, array( 'rp', 'resetpass', 'newaccount' ) ) ) { $title = __( 'Set password', 'kkart' ); } else { $title = __( 'Lost password', 'kkart' ); } break; default: $title = ''; break; } /** * Filters the page title used for my-account endpoints. * * @since 2.6.0 * @since 4.6.0 Added $action parameter. * * @see get_endpoint_title() * * @param string $title Default title. * @param string $endpoint Endpoint key. * @param string $action Optional action or variation within the endpoint. */ return apply_filters( 'kkart_endpoint_' . $endpoint . '_title', $title, $endpoint, $action ); } /** * Endpoint mask describing the places the endpoint should be added. * * @since 2.6.2 * @return int */ public function get_endpoints_mask() { if ( 'page' === get_option( 'show_on_front' ) ) { $page_on_front = get_option( 'page_on_front' ); $myaccount_page_id = get_option( 'kkart_myaccount_page_id' ); $checkout_page_id = get_option( 'kkart_checkout_page_id' ); if ( in_array( $page_on_front, array( $myaccount_page_id, $checkout_page_id ), true ) ) { return EP_ROOT | EP_PAGES; } } return EP_PAGES; } /** * Add endpoints for query vars. */ public function add_endpoints() { $mask = $this->get_endpoints_mask(); foreach ( $this->get_query_vars() as $key => $var ) { if ( ! empty( $var ) ) { add_rewrite_endpoint( $var, $mask ); } } } /** * Add query vars. * * @param array $vars Query vars. * @return array */ public function add_query_vars( $vars ) { foreach ( $this->get_query_vars() as $key => $var ) { $vars[] = $key; } return $vars; } /** * Get query vars. * * @return array */ public function get_query_vars() { return apply_filters( 'kkart_get_query_vars', $this->query_vars ); } /** * Get query current active query var. * * @return string */ public function get_current_endpoint() { global $wp; foreach ( $this->get_query_vars() as $key => $value ) { if ( isset( $wp->query_vars[ $key ] ) ) { return $key; } } return ''; } /** * Parse the request and look for query vars - endpoints may not be supported. */ public function parse_request() { global $wp; // phpcs:disable WordPress.Security.NonceVerification.Recommended // Map query vars to their keys, or get them if endpoints are not supported. foreach ( $this->get_query_vars() as $key => $var ) { if ( isset( $_GET[ $var ] ) ) { $wp->query_vars[ $key ] = sanitize_text_field( wp_unslash( $_GET[ $var ] ) ); } elseif ( isset( $wp->query_vars[ $var ] ) ) { $wp->query_vars[ $key ] = $wp->query_vars[ $var ]; } } // phpcs:enable WordPress.Security.NonceVerification.Recommended } /** * Are we currently on the front page? * * @param WP_Query $q Query instance. * @return bool */ private function is_showing_page_on_front( $q ) { return ( $q->is_home() && ! $q->is_posts_page ) && 'page' === get_option( 'show_on_front' ); } /** * Is the front page a page we define? * * @param int $page_id Page ID. * @return bool */ private function page_on_front_is( $page_id ) { return absint( get_option( 'page_on_front' ) ) === absint( $page_id ); } /** * Hook into pre_get_posts to do the main product query. * * @param WP_Query $q Query instance. */ public function pre_get_posts( $q ) { // We only want to affect the main query. if ( ! $q->is_main_query() ) { return; } // Fixes for queries on static homepages. if ( $this->is_showing_page_on_front( $q ) ) { // Fix for endpoints on the homepage. if ( ! $this->page_on_front_is( $q->get( 'page_id' ) ) ) { $_query = wp_parse_args( $q->query ); if ( ! empty( $_query ) && array_intersect( array_keys( $_query ), array_keys( $this->get_query_vars() ) ) ) { $q->is_page = true; $q->is_home = false; $q->is_singular = true; $q->set( 'page_id', (int) get_option( 'page_on_front' ) ); add_filter( 'redirect_canonical', '__return_false' ); } } // When orderby is set, WordPress shows posts on the front-page. Get around that here. if ( $this->page_on_front_is( kkart_get_page_id( 'shop' ) ) ) { $_query = wp_parse_args( $q->query ); if ( empty( $_query ) || ! array_diff( array_keys( $_query ), array( 'preview', 'page', 'paged', 'cpage', 'orderby' ) ) ) { $q->set( 'page_id', (int) get_option( 'page_on_front' ) ); $q->is_page = true; $q->is_home = false; // WP supporting themes show post type archive. if ( current_theme_supports( 'kkart' ) ) { $q->set( 'post_type', 'product' ); } else { $q->is_singular = true; } } } elseif ( ! empty( $_GET['orderby'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $q->set( 'page_id', (int) get_option( 'page_on_front' ) ); $q->is_page = true; $q->is_home = false; $q->is_singular = true; } } // Fix product feeds. if ( $q->is_feed() && $q->is_post_type_archive( 'product' ) ) { $q->is_comment_feed = false; } // Special check for shops with the PRODUCT POST TYPE ARCHIVE on front. if ( current_theme_supports( 'kkart' ) && $q->is_page() && 'page' === get_option( 'show_on_front' ) && absint( $q->get( 'page_id' ) ) === kkart_get_page_id( 'shop' ) ) { // This is a front-page shop. $q->set( 'post_type', 'product' ); $q->set( 'page_id', '' ); if ( isset( $q->query['paged'] ) ) { $q->set( 'paged', $q->query['paged'] ); } // Define a variable so we know this is the front page shop later on. kkart_maybe_define_constant( 'SHOP_IS_ON_FRONT', true ); // Get the actual WP page to avoid errors and let us use is_front_page(). // This is hacky but works. Awaiting https://core.trac.wordpress.org/ticket/21096. global $wp_post_types; $shop_page = get_post( kkart_get_page_id( 'shop' ) ); $wp_post_types['product']->ID = $shop_page->ID; $wp_post_types['product']->post_title = $shop_page->post_title; $wp_post_types['product']->post_name = $shop_page->post_name; $wp_post_types['product']->post_type = $shop_page->post_type; $wp_post_types['product']->ancestors = get_ancestors( $shop_page->ID, $shop_page->post_type ); // Fix conditional Functions like is_front_page. $q->is_singular = false; $q->is_post_type_archive = true; $q->is_archive = true; $q->is_page = true; // Remove post type archive name from front page title tag. add_filter( 'post_type_archive_title', '__return_empty_string', 5 ); // Fix WP SEO. if ( class_exists( 'WPSEO_Meta' ) ) { add_filter( 'wpseo_metadesc', array( $this, 'wpseo_metadesc' ) ); add_filter( 'wpseo_metakey', array( $this, 'wpseo_metakey' ) ); } } elseif ( ! $q->is_post_type_archive( 'product' ) && ! $q->is_tax( get_object_taxonomies( 'product' ) ) ) { // Only apply to product categories, the product post archive, the shop page, product tags, and product attribute taxonomies. return; } $this->product_query( $q ); } /** * Handler for the 'the_posts' WP filter. * * @param array $posts Posts from WP Query. * @param WP_Query $query Current query. * * @return array */ public function handle_get_posts( $posts, $query ) { if ( 'product_query' !== $query->get( 'kkart_query' ) ) { return $posts; } $this->remove_product_query_filters( $posts ); return $posts; } /** * Pre_get_posts above may adjust the main query to add Kkart logic. When this query is done, we need to ensure * all custom filters are removed. * * This is done here during the_posts filter. The input is not changed. * * @param array $posts Posts from WP Query. * @return array */ public function remove_product_query_filters( $posts ) { $this->remove_ordering_args(); remove_filter( 'posts_clauses', array( $this, 'price_filter_post_clauses' ), 10, 2 ); return $posts; } /** * This function used to be hooked to found_posts and adjust the posts count when the filtering by attribute * widget was used and variable products were present. Now it isn't hooked anymore and does nothing but return * the input unchanged, since the pull request in which it was introduced has been reverted. * * @since 4.4.0 * @param int $count Original posts count, as supplied by the found_posts filter. * @param WP_Query $query The current WP_Query object. * * @return int Adjusted posts count. */ public function adjust_posts_count( $count, $query ) { return $count; } /** * Instance version of get_layered_nav_chosen_attributes, needed for unit tests. * * @return array */ protected function get_layered_nav_chosen_attributes_inst() { return self::get_layered_nav_chosen_attributes(); } /** * Get the posts (or the ids of the posts) found in the current WP loop. * * @return array Array of posts or post ids. */ protected function get_current_posts() { return $GLOBALS['wp_query']->posts; } /** * WP SEO meta description. * * Hooked into wpseo_ hook already, so no need for function_exist. * * @return string */ public function wpseo_metadesc() { return WPSEO_Meta::get_value( 'metadesc', kkart_get_page_id( 'shop' ) ); } /** * WP SEO meta key. * * Hooked into wpseo_ hook already, so no need for function_exist. * * @return string */ public function wpseo_metakey() { return WPSEO_Meta::get_value( 'metakey', kkart_get_page_id( 'shop' ) ); } /** * Query the products, applying sorting/ordering etc. * This applies to the main WordPress loop. * * @param WP_Query $q Query instance. */ public function product_query( $q ) { if ( ! is_feed() ) { $ordering = $this->get_catalog_ordering_args(); $q->set( 'orderby', $ordering['orderby'] ); $q->set( 'order', $ordering['order'] ); if ( isset( $ordering['meta_key'] ) ) { $q->set( 'meta_key', $ordering['meta_key'] ); } } // Query vars that affect posts shown. $q->set( 'meta_query', $this->get_meta_query( $q->get( 'meta_query' ), true ) ); $q->set( 'tax_query', $this->get_tax_query( $q->get( 'tax_query' ), true ) ); $q->set( 'kkart_query', 'product_query' ); $q->set( 'post__in', array_unique( (array) apply_filters( 'loop_shop_post_in', array() ) ) ); // Work out how many products to query. $q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_shop_per_page', kkart_get_default_products_per_row() * kkart_get_default_product_rows_per_page() ) ); // Store reference to this query. self::$product_query = $q; // Additonal hooks to change WP Query. add_filter( 'posts_clauses', array( $this, 'price_filter_post_clauses' ), 10, 2 ); add_filter( 'the_posts', array( $this, 'handle_get_posts' ), 10, 2 ); do_action( 'kkart_product_query', $q, $this ); } /** * Remove the query. */ public function remove_product_query() { remove_action( 'pre_get_posts', array( $this, 'pre_get_posts' ) ); } /** * Remove ordering queries. */ public function remove_ordering_args() { remove_filter( 'posts_clauses', array( $this, 'order_by_price_asc_post_clauses' ) ); remove_filter( 'posts_clauses', array( $this, 'order_by_price_desc_post_clauses' ) ); remove_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) ); remove_filter( 'posts_clauses', array( $this, 'order_by_rating_post_clauses' ) ); } /** * Returns an array of arguments for ordering products based on the selected values. * * @param string $orderby Order by param. * @param string $order Order param. * @return array */ public function get_catalog_ordering_args( $orderby = '', $order = '' ) { // Get ordering from query string unless defined. if ( ! $orderby ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended $orderby_value = isset( $_GET['orderby'] ) ? kkart_clean( (string) wp_unslash( $_GET['orderby'] ) ) : kkart_clean( get_query_var( 'orderby' ) ); if ( ! $orderby_value ) { if ( is_search() ) { $orderby_value = 'relevance'; } else { $orderby_value = apply_filters( 'kkart_default_catalog_orderby', get_option( 'kkart_default_catalog_orderby', 'menu_order' ) ); } } // Get order + orderby args from string. $orderby_value = is_array( $orderby_value ) ? $orderby_value : explode( '-', $orderby_value ); $orderby = esc_attr( $orderby_value[0] ); $order = ! empty( $orderby_value[1] ) ? $orderby_value[1] : $order; } // Convert to correct format. $orderby = strtolower( is_array( $orderby ) ? (string) current( $orderby ) : (string) $orderby ); $order = strtoupper( is_array( $order ) ? (string) current( $order ) : (string) $order ); $args = array( 'orderby' => $orderby, 'order' => ( 'DESC' === $order ) ? 'DESC' : 'ASC', 'meta_key' => '', // @codingStandardsIgnoreLine ); switch ( $orderby ) { case 'id': $args['orderby'] = 'ID'; break; case 'menu_order': $args['orderby'] = 'menu_order title'; break; case 'title': $args['orderby'] = 'title'; $args['order'] = ( 'DESC' === $order ) ? 'DESC' : 'ASC'; break; case 'relevance': $args['orderby'] = 'relevance'; $args['order'] = 'DESC'; break; case 'rand': $args['orderby'] = 'rand'; // @codingStandardsIgnoreLine break; case 'date': $args['orderby'] = 'date ID'; $args['order'] = ( 'ASC' === $order ) ? 'ASC' : 'DESC'; break; case 'price': $callback = 'DESC' === $order ? 'order_by_price_desc_post_clauses' : 'order_by_price_asc_post_clauses'; add_filter( 'posts_clauses', array( $this, $callback ) ); break; case 'popularity': add_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) ); break; case 'rating': add_filter( 'posts_clauses', array( $this, 'order_by_rating_post_clauses' ) ); break; } return apply_filters( 'kkart_get_catalog_ordering_args', $args, $orderby, $order ); } /** * Custom query used to filter products by price. * * @since 3.6.0 * * @param array $args Query args. * @param WP_Query $wp_query WP_Query object. * * @return array */ public function price_filter_post_clauses( $args, $wp_query ) { global $wpdb; // phpcs:ignore WordPress.Security.NonceVerification.Recommended if ( ! $wp_query->is_main_query() || ( ! isset( $_GET['max_price'] ) && ! isset( $_GET['min_price'] ) ) ) { return $args; } // phpcs:disable WordPress.Security.NonceVerification.Recommended $current_min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0; $current_max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX; // phpcs:enable WordPress.Security.NonceVerification.Recommended /** * Adjust if the store taxes are not displayed how they are stored. * Kicks in when prices excluding tax are displayed including tax. */ if ( kkart_tax_enabled() && 'incl' === get_option( 'kkart_tax_display_shop' ) && ! kkart_prices_include_tax() ) { $tax_class = apply_filters( 'kkart_price_filter_widget_tax_class', '' ); // Uses standard tax class. $tax_rates = KKART_Tax::get_rates( $tax_class ); if ( $tax_rates ) { $current_min_price -= KKART_Tax::get_tax_total( KKART_Tax::calc_inclusive_tax( $current_min_price, $tax_rates ) ); $current_max_price -= KKART_Tax::get_tax_total( KKART_Tax::calc_inclusive_tax( $current_max_price, $tax_rates ) ); } } $args['join'] = $this->append_product_sorting_table_join( $args['join'] ); $args['where'] .= $wpdb->prepare( ' AND kkart_product_meta_lookup.min_price >= %f AND kkart_product_meta_lookup.max_price <= %f ', $current_min_price, $current_max_price ); return $args; } /** * Handle numeric price sorting. * * @param array $args Query args. * @return array */ public function order_by_price_asc_post_clauses( $args ) { $args['join'] = $this->append_product_sorting_table_join( $args['join'] ); $args['orderby'] = ' kkart_product_meta_lookup.min_price ASC, kkart_product_meta_lookup.product_id ASC '; return $args; } /** * Handle numeric price sorting. * * @param array $args Query args. * @return array */ public function order_by_price_desc_post_clauses( $args ) { $args['join'] = $this->append_product_sorting_table_join( $args['join'] ); $args['orderby'] = ' kkart_product_meta_lookup.max_price DESC, kkart_product_meta_lookup.product_id DESC '; return $args; } /** * WP Core does not let us change the sort direction for individual orderby params - https://core.trac.wordpress.org/ticket/17065. * * This lets us sort by meta value desc, and have a second orderby param. * * @param array $args Query args. * @return array */ public function order_by_popularity_post_clauses( $args ) { $args['join'] = $this->append_product_sorting_table_join( $args['join'] ); $args['orderby'] = ' kkart_product_meta_lookup.total_sales DESC, kkart_product_meta_lookup.product_id DESC '; return $args; } /** * Order by rating post clauses. * * @param array $args Query args. * @return array */ public function order_by_rating_post_clauses( $args ) { $args['join'] = $this->append_product_sorting_table_join( $args['join'] ); $args['orderby'] = ' kkart_product_meta_lookup.average_rating DESC, kkart_product_meta_lookup.rating_count DESC, kkart_product_meta_lookup.product_id DESC '; return $args; } /** * Join kkart_product_meta_lookup to posts if not already joined. * * @param string $sql SQL join. * @return string */ private function append_product_sorting_table_join( $sql ) { global $wpdb; if ( ! strstr( $sql, 'kkart_product_meta_lookup' ) ) { $sql .= " LEFT JOIN {$wpdb->kkart_product_meta_lookup} kkart_product_meta_lookup ON $wpdb->posts.ID = kkart_product_meta_lookup.product_id "; } return $sql; } /** * Appends meta queries to an array. * * @param array $meta_query Meta query. * @param bool $main_query If is main query. * @return array */ public function get_meta_query( $meta_query = array(), $main_query = false ) { if ( ! is_array( $meta_query ) ) { $meta_query = array(); } return array_filter( apply_filters( 'kkart_product_query_meta_query', $meta_query, $this ) ); } /** * Appends tax queries to an array. * * @param array $tax_query Tax query. * @param bool $main_query If is main query. * @return array */ public function get_tax_query( $tax_query = array(), $main_query = false ) { if ( ! is_array( $tax_query ) ) { $tax_query = array( 'relation' => 'AND', ); } // Layered nav filters on terms. if ( $main_query ) { foreach ( $this->get_layered_nav_chosen_attributes() as $taxonomy => $data ) { $tax_query[] = array( 'taxonomy' => $taxonomy, 'field' => 'slug', 'terms' => $data['terms'], 'operator' => 'and' === $data['query_type'] ? 'AND' : 'IN', 'include_children' => false, ); } } $product_visibility_terms = kkart_get_product_visibility_term_ids(); $product_visibility_not_in = array( is_search() && $main_query ? $product_visibility_terms['exclude-from-search'] : $product_visibility_terms['exclude-from-catalog'] ); // Hide out of stock products. if ( 'yes' === get_option( 'kkart_hide_out_of_stock_items' ) ) { $product_visibility_not_in[] = $product_visibility_terms['outofstock']; } // phpcs:disable WordPress.Security.NonceVerification.Recommended // Filter by rating. if ( isset( $_GET['rating_filter'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $rating_filter = array_filter( array_map( 'absint', explode( ',', wp_unslash( $_GET['rating_filter'] ) ) ) ); $rating_terms = array(); for ( $i = 1; $i <= 5; $i ++ ) { if ( in_array( $i, $rating_filter, true ) && isset( $product_visibility_terms[ 'rated-' . $i ] ) ) { $rating_terms[] = $product_visibility_terms[ 'rated-' . $i ]; } } if ( ! empty( $rating_terms ) ) { $tax_query[] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $rating_terms, 'operator' => 'IN', 'rating_filter' => true, ); } } // phpcs:enable WordPress.Security.NonceVerification.Recommended if ( ! empty( $product_visibility_not_in ) ) { $tax_query[] = array( 'taxonomy' => 'product_visibility', 'field' => 'term_taxonomy_id', 'terms' => $product_visibility_not_in, 'operator' => 'NOT IN', ); } return array_filter( apply_filters( 'kkart_product_query_tax_query', $tax_query, $this ) ); } /** * Get the main query which product queries ran against. * * @return WP_Query */ public static function get_main_query() { return self::$product_query; } /** * Get the tax query which was used by the main query. * * @return array */ public static function get_main_tax_query() { $tax_query = isset( self::$product_query->tax_query, self::$product_query->tax_query->queries ) ? self::$product_query->tax_query->queries : array(); return $tax_query; } /** * Get the meta query which was used by the main query. * * @return array */ public static function get_main_meta_query() { $args = self::$product_query->query_vars; $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array(); return $meta_query; } /** * Based on WP_Query::parse_search */ public static function get_main_search_query_sql() { global $wpdb; $args = self::$product_query->query_vars; $search_terms = isset( $args['search_terms'] ) ? $args['search_terms'] : array(); $sql = array(); foreach ( $search_terms as $term ) { // Terms prefixed with '-' should be excluded. $include = '-' !== substr( $term, 0, 1 ); if ( $include ) { $like_op = 'LIKE'; $andor_op = 'OR'; } else { $like_op = 'NOT LIKE'; $andor_op = 'AND'; $term = substr( $term, 1 ); } $like = '%' . $wpdb->esc_like( $term ) . '%'; // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared $sql[] = $wpdb->prepare( "(($wpdb->posts.post_title $like_op %s) $andor_op ($wpdb->posts.post_excerpt $like_op %s) $andor_op ($wpdb->posts.post_content $like_op %s))", $like, $like, $like ); } if ( ! empty( $sql ) && ! is_user_logged_in() ) { $sql[] = "($wpdb->posts.post_password = '')"; } return implode( ' AND ', $sql ); } /** * Get an array of attributes and terms selected with the layered nav widget. * * @return array */ public static function get_layered_nav_chosen_attributes() { // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! is_array( self::$chosen_attributes ) ) { self::$chosen_attributes = array(); if ( ! empty( $_GET ) ) { foreach ( $_GET as $key => $value ) { if ( 0 === strpos( $key, 'filter_' ) ) { $attribute = kkart_sanitize_taxonomy_name( str_replace( 'filter_', '', $key ) ); $taxonomy = kkart_attribute_taxonomy_name( $attribute ); $filter_terms = ! empty( $value ) ? explode( ',', kkart_clean( wp_unslash( $value ) ) ) : array(); if ( empty( $filter_terms ) || ! taxonomy_exists( $taxonomy ) || ! kkart_attribute_taxonomy_id_by_name( $attribute ) ) { continue; } $query_type = ! empty( $_GET[ 'query_type_' . $attribute ] ) && in_array( $_GET[ 'query_type_' . $attribute ], array( 'and', 'or' ), true ) ? kkart_clean( wp_unslash( $_GET[ 'query_type_' . $attribute ] ) ) : ''; self::$chosen_attributes[ $taxonomy ]['terms'] = array_map( 'sanitize_title', $filter_terms ); // Ensures correct encoding. self::$chosen_attributes[ $taxonomy ]['query_type'] = $query_type ? $query_type : apply_filters( 'kkart_layered_nav_default_query_type', 'and' ); } } } } return self::$chosen_attributes; // phpcs:disable WordPress.Security.NonceVerification.Recommended } /** * Remove the add-to-cart param from pagination urls. * * @param string $url URL. * @return string */ public function remove_add_to_cart_pagination( $url ) { return remove_query_arg( 'add-to-cart', $url ); } /** * Return a meta query for filtering by rating. * * @deprecated 3.0.0 Replaced with taxonomy. * @return array */ public function rating_filter_meta_query() { return array(); } /** * Returns a meta query to handle product visibility. * * @deprecated 3.0.0 Replaced with taxonomy. * @param string $compare (default: 'IN'). * @return array */ public function visibility_meta_query( $compare = 'IN' ) { return array(); } /** * Returns a meta query to handle product stock status. * * @deprecated 3.0.0 Replaced with taxonomy. * @param string $status (default: 'instock'). * @return array */ public function stock_status_meta_query( $status = 'instock' ) { return array(); } /** * Layered nav init. * * @deprecated 2.6.0 */ public function layered_nav_init() { kkart_deprecated_function( 'layered_nav_init', '2.6' ); } /** * Get an unpaginated list all product IDs (both filtered and unfiltered). Makes use of transients. * * @deprecated 2.6.0 due to performance concerns */ public function get_products_in_view() { kkart_deprecated_function( 'get_products_in_view', '2.6' ); } /** * Layered Nav post filter. * * @deprecated 2.6.0 due to performance concerns * * @param mixed $deprecated Deprecated. */ public function layered_nav_query( $deprecated ) { kkart_deprecated_function( 'layered_nav_query', '2.6' ); } /** * Search post excerpt. * * @param string $where Where clause. * * @deprecated 3.2.0 - Not needed anymore since WordPress 4.5. */ public function search_post_excerpt( $where = '' ) { kkart_deprecated_function( 'KKART_Query::search_post_excerpt', '3.2.0', 'Excerpt added to search query by default since WordPress 4.5.' ); return $where; } /** * Remove the posts_where filter. * * @deprecated 3.2.0 - Nothing to remove anymore because search_post_excerpt() is deprecated. */ public function remove_posts_where() { kkart_deprecated_function( 'KKART_Query::remove_posts_where', '3.2.0', 'Nothing to remove anymore because search_post_excerpt() is deprecated.' ); } } PK!sy5 class-kkart-logger.phpnu[' . esc_html( is_object( $handler ) ? get_class( $handler ) : $handler ) . '', 'KKART_Log_Handler_Interface' ), '3.0' ); } } } // Support the constant as long as a valid log level has been set for it. if ( null === $threshold ) { $threshold = Constants::get_constant( 'KKART_LOG_THRESHOLD' ); if ( null !== $threshold && ! KKART_Log_Levels::is_valid_level( $threshold ) ) { $threshold = null; } } if ( null !== $threshold ) { $threshold = KKART_Log_Levels::get_level_severity( $threshold ); } $this->handlers = $register_handlers; $this->threshold = $threshold; } /** * Determine whether to handle or ignore log. * * @param string $level emergency|alert|critical|error|warning|notice|info|debug. * @return bool True if the log should be handled. */ protected function should_handle( $level ) { if ( null === $this->threshold ) { return true; } return $this->threshold <= KKART_Log_Levels::get_level_severity( $level ); } /** * Add a log entry. * * This is not the preferred method for adding log messages. Please use log() or any one of * the level methods (debug(), info(), etc.). This method may be deprecated in the future. * * @param string $handle File handle. * @param string $message Message to log. * @param string $level Logging level. * @return bool */ public function add( $handle, $message, $level = KKART_Log_Levels::NOTICE ) { $message = apply_filters( 'kkart_logger_add_message', $message, $handle ); $this->log( $level, $message, array( 'source' => $handle, '_legacy' => true, ) ); return true; } /** * Add a log entry. * * @param string $level One of the following: * 'emergency': System is unusable. * 'alert': Action must be taken immediately. * 'critical': Critical conditions. * 'error': Error conditions. * 'warning': Warning conditions. * 'notice': Normal but significant condition. * 'info': Informational messages. * 'debug': Debug-level messages. * @param string $message Log message. * @param array $context Optional. Additional information for log handlers. */ public function log( $level, $message, $context = array() ) { if ( ! KKART_Log_Levels::is_valid_level( $level ) ) { /* translators: 1: KKART_Logger::log 2: level */ kkart_doing_it_wrong( __METHOD__, sprintf( __( '%1$s was called with an invalid level "%2$s".', 'kkart' ), 'KKART_Logger::log', $level ), '3.0' ); } if ( $this->should_handle( $level ) ) { $timestamp = current_time( 'timestamp', 1 ); $message = apply_filters( 'kkart_logger_log_message', $message, $level, $context ); foreach ( $this->handlers as $handler ) { $handler->handle( $timestamp, $level, $message, $context ); } } } /** * Adds an emergency level message. * * System is unusable. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function emergency( $message, $context = array() ) { $this->log( KKART_Log_Levels::EMERGENCY, $message, $context ); } /** * Adds an alert level message. * * Action must be taken immediately. * Example: Entire website down, database unavailable, etc. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function alert( $message, $context = array() ) { $this->log( KKART_Log_Levels::ALERT, $message, $context ); } /** * Adds a critical level message. * * Critical conditions. * Example: Application component unavailable, unexpected exception. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function critical( $message, $context = array() ) { $this->log( KKART_Log_Levels::CRITICAL, $message, $context ); } /** * Adds an error level message. * * Runtime errors that do not require immediate action but should typically be logged * and monitored. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function error( $message, $context = array() ) { $this->log( KKART_Log_Levels::ERROR, $message, $context ); } /** * Adds a warning level message. * * Exceptional occurrences that are not errors. * * Example: Use of deprecated APIs, poor use of an API, undesirable things that are not * necessarily wrong. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function warning( $message, $context = array() ) { $this->log( KKART_Log_Levels::WARNING, $message, $context ); } /** * Adds a notice level message. * * Normal but significant events. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function notice( $message, $context = array() ) { $this->log( KKART_Log_Levels::NOTICE, $message, $context ); } /** * Adds a info level message. * * Interesting events. * Example: User logs in, SQL logs. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function info( $message, $context = array() ) { $this->log( KKART_Log_Levels::INFO, $message, $context ); } /** * Adds a debug level message. * * Detailed debug information. * * @see KKART_Logger::log * * @param string $message Message to log. * @param array $context Log context. */ public function debug( $message, $context = array() ) { $this->log( KKART_Log_Levels::DEBUG, $message, $context ); } /** * Clear entries for a chosen file/source. * * @param string $source Source/handle to clear. * @return bool */ public function clear( $source = '' ) { if ( ! $source ) { return false; } foreach ( $this->handlers as $handler ) { if ( is_callable( array( $handler, 'clear' ) ) ) { $handler->clear( $source ); } } return true; } /** * Clear all logs older than a defined number of days. Defaults to 30 days. * * @since 3.4.0 */ public function clear_expired_logs() { $days = absint( apply_filters( 'kkart_logger_days_to_retain_logs', 30 ) ); $timestamp = strtotime( "-{$days} days" ); foreach ( $this->handlers as $handler ) { if ( is_callable( array( $handler, 'delete_logs_before_timestamp' ) ) ) { $handler->delete_logs_before_timestamp( $timestamp ); } } } } PK!YY#class-kkart-geolite-integration.phpnu[database = $database; } /** * Get country 2-letters ISO by IP address. * Returns empty string when not able to find any ISO code. * * @param string $ip_address User IP address. * @return string * @deprecated 3.9.0 */ public function get_country_iso( $ip_address ) { kkart_deprecated_function( 'get_country_iso', '3.9.0' ); $iso_code = ''; try { $reader = new MaxMind\Db\Reader( $this->database ); // phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound $data = $reader->get( $ip_address ); if ( isset( $data['country']['iso_code'] ) ) { $iso_code = $data['country']['iso_code']; } $reader->close(); } catch ( Exception $e ) { $this->log( $e->getMessage(), 'warning' ); } return sanitize_text_field( strtoupper( $iso_code ) ); } /** * Logging method. * * @param string $message Log message. * @param string $level Log level. * Available options: 'emergency', 'alert', * 'critical', 'error', 'warning', 'notice', * 'info' and 'debug'. * Defaults to 'info'. */ private function log( $message, $level = 'info' ) { if ( is_null( $this->log ) ) { $this->log = kkart_get_logger(); } $this->log->log( $level, $message, array( 'source' => 'geoip' ) ); } } PK!7.log-handlers/class-kkart-log-handler-email.phpnu[add_email( $recipient ); } } else { $this->add_email( $recipients ); } $this->set_threshold( $threshold ); add_action( 'shutdown', array( $this, 'send_log_email' ) ); } /** * Set handler severity threshold. * * @param string $level emergency|alert|critical|error|warning|notice|info|debug. */ public function set_threshold( $level ) { $this->threshold = KKART_Log_Levels::get_level_severity( $level ); } /** * Determine whether handler should handle log. * * @param string $level emergency|alert|critical|error|warning|notice|info|debug. * @return bool True if the log should be handled. */ protected function should_handle( $level ) { return $this->threshold <= KKART_Log_Levels::get_level_severity( $level ); } /** * Handle a log entry. * * @param int $timestamp Log timestamp. * @param string $level emergency|alert|critical|error|warning|notice|info|debug. * @param string $message Log message. * @param array $context Optional. Additional information for log handlers. * * @return bool False if value was not handled and true if value was handled. */ public function handle( $timestamp, $level, $message, $context ) { if ( $this->should_handle( $level ) ) { $this->add_log( $timestamp, $level, $message, $context ); return true; } return false; } /** * Send log email. * * @return bool True if email is successfully sent otherwise false. */ public function send_log_email() { $result = false; if ( ! empty( $this->logs ) ) { $subject = $this->get_subject(); $body = $this->get_body(); $result = wp_mail( $this->recipients, $subject, $body ); $this->clear_logs(); } return $result; } /** * Build subject for log email. * * @return string subject */ protected function get_subject() { $site_name = get_bloginfo( 'name' ); $max_level = strtoupper( KKART_Log_Levels::get_severity_level( $this->max_severity ) ); $log_count = count( $this->logs ); return sprintf( /* translators: 1: Site name 2: Maximum level 3: Log count */ _n( '[%1$s] %2$s: %3$s Kkart log message', '[%1$s] %2$s: %3$s Kkart log messages', $log_count, 'kkart' ), $site_name, $max_level, $log_count ); } /** * Build body for log email. * * @return string body */ protected function get_body() { $site_name = get_bloginfo( 'name' ); $entries = implode( PHP_EOL, $this->logs ); $log_count = count( $this->logs ); return _n( 'You have received the following Kkart log message:', 'You have received the following Kkart log messages:', $log_count, 'kkart' ) . PHP_EOL . PHP_EOL . $entries . PHP_EOL . PHP_EOL /* translators: %s: Site name */ . sprintf( __( 'Visit %s admin area:', 'kkart' ), $site_name ) . PHP_EOL . admin_url(); } /** * Adds an email to the list of recipients. * * @param string $email Email address to add. */ public function add_email( $email ) { array_push( $this->recipients, $email ); } /** * Add log message. * * @param int $timestamp Log timestamp. * @param string $level emergency|alert|critical|error|warning|notice|info|debug. * @param string $message Log message. * @param array $context Additional information for log handlers. */ protected function add_log( $timestamp, $level, $message, $context ) { $this->logs[] = $this->format_entry( $timestamp, $level, $message, $context ); $log_severity = KKART_Log_Levels::get_level_severity( $level ); if ( $this->max_severity < $log_severity ) { $this->max_severity = $log_severity; } } /** * Clear log messages. */ protected function clear_logs() { $this->logs = array(); } } PK!u11+log-handlers/class-kkart-log-handler-db.phpnu[get_log_source(); } return $this->add( $timestamp, $level, $message, $source, $context ); } /** * Add a log entry to chosen file. * * @param int $timestamp Log timestamp. * @param string $level emergency|alert|critical|error|warning|notice|info|debug. * @param string $message Log message. * @param string $source Log source. Useful for filtering and sorting. * @param array $context Context will be serialized and stored in database. * * @return bool True if write was successful. */ protected static function add( $timestamp, $level, $message, $source, $context ) { global $wpdb; $insert = array( 'timestamp' => date( 'Y-m-d H:i:s', $timestamp ), 'level' => KKART_Log_Levels::get_level_severity( $level ), 'message' => $message, 'source' => $source, ); $format = array( '%s', '%d', '%s', '%s', '%s', // possible serialized context. ); if ( ! empty( $context ) ) { $insert['context'] = serialize( $context ); // @codingStandardsIgnoreLine. } return false !== $wpdb->insert( "{$wpdb->prefix}kkart_log", $insert, $format ); } /** * Clear all logs from the DB. * * @return bool True if flush was successful. */ public static function flush() { global $wpdb; return $wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}kkart_log" ); } /** * Clear entries for a chosen handle/source. * * @param string $source Log source. * @return bool */ public function clear( $source ) { global $wpdb; return $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}kkart_log WHERE source = %s", $source ) ); } /** * Delete selected logs from DB. * * @param int|string|array $log_ids Log ID or array of Log IDs to be deleted. * * @return bool */ public static function delete( $log_ids ) { global $wpdb; if ( ! is_array( $log_ids ) ) { $log_ids = array( $log_ids ); } $format = array_fill( 0, count( $log_ids ), '%d' ); $query_in = '(' . implode( ',', $format ) . ')'; return $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}kkart_log WHERE log_id IN {$query_in}", $log_ids ) ); // @codingStandardsIgnoreLine. } /** * Delete all logs older than a defined timestamp. * * @since 3.4.0 * @param integer $timestamp Timestamp to delete logs before. */ public static function delete_logs_before_timestamp( $timestamp = 0 ) { if ( ! $timestamp ) { return; } global $wpdb; $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}kkart_log WHERE timestamp < %s", date( 'Y-m-d H:i:s', $timestamp ) ) ); } /** * Get appropriate source based on file name. * * Try to provide an appropriate source in case none is provided. * * @return string Text to use as log source. "" (empty string) if none is found. */ protected static function get_log_source() { static $ignore_files = array( 'class-kkart-log-handler-db', 'class-kkart-logger' ); /** * PHP < 5.3.6 correct behavior * * @see http://php.net/manual/en/function.debug-backtrace.php#refsect1-function.debug-backtrace-parameters */ if ( Constants::is_defined( 'DEBUG_BACKTRACE_IGNORE_ARGS' ) ) { $debug_backtrace_arg = DEBUG_BACKTRACE_IGNORE_ARGS; // phpcs:ignore PHPCompatibility.Constants.NewConstants.debug_backtrace_ignore_argsFound } else { $debug_backtrace_arg = false; } $trace = debug_backtrace( $debug_backtrace_arg ); // @codingStandardsIgnoreLine. foreach ( $trace as $t ) { if ( isset( $t['file'] ) ) { $filename = pathinfo( $t['file'], PATHINFO_FILENAME ); if ( ! in_array( $filename, $ignore_files, true ) ) { return $filename; } } } return ''; } } PK!>>---log-handlers/class-kkart-log-handler-file.phpnu[log_size_limit = apply_filters( 'kkart_log_file_size_limit', $log_size_limit ); add_action( 'plugins_loaded', array( $this, 'write_cached_logs' ) ); } /** * Destructor. * * Cleans up open file handles. */ public function __destruct() { foreach ( $this->handles as $handle ) { if ( is_resource( $handle ) ) { fclose( $handle ); // @codingStandardsIgnoreLine. } } } /** * Handle a log entry. * * @param int $timestamp Log timestamp. * @param string $level emergency|alert|critical|error|warning|notice|info|debug. * @param string $message Log message. * @param array $context { * Additional information for log handlers. * * @type string $source Optional. Determines log file to write to. Default 'log'. * @type bool $_legacy Optional. Default false. True to use outdated log format * originally used in deprecated KKART_Logger::add calls. * } * * @return bool False if value was not handled and true if value was handled. */ public function handle( $timestamp, $level, $message, $context ) { if ( isset( $context['source'] ) && $context['source'] ) { $handle = $context['source']; } else { $handle = 'log'; } $entry = self::format_entry( $timestamp, $level, $message, $context ); return $this->add( $entry, $handle ); } /** * Builds a log entry text from timestamp, level and message. * * @param int $timestamp Log timestamp. * @param string $level emergency|alert|critical|error|warning|notice|info|debug. * @param string $message Log message. * @param array $context Additional information for log handlers. * * @return string Formatted log entry. */ protected static function format_entry( $timestamp, $level, $message, $context ) { if ( isset( $context['_legacy'] ) && true === $context['_legacy'] ) { if ( isset( $context['source'] ) && $context['source'] ) { $handle = $context['source']; } else { $handle = 'log'; } $message = apply_filters( 'kkart_logger_add_message', $message, $handle ); $time = date_i18n( 'm-d-Y @ H:i:s' ); $entry = "{$time} - {$message}"; } else { $entry = parent::format_entry( $timestamp, $level, $message, $context ); } return $entry; } /** * Open log file for writing. * * @param string $handle Log handle. * @param string $mode Optional. File mode. Default 'a'. * @return bool Success. */ protected function open( $handle, $mode = 'a' ) { if ( $this->is_open( $handle ) ) { return true; } $file = self::get_log_file_path( $handle ); if ( $file ) { if ( ! file_exists( $file ) ) { $temphandle = @fopen( $file, 'w+' ); // @codingStandardsIgnoreLine. @fclose( $temphandle ); // @codingStandardsIgnoreLine. if ( Constants::is_defined( 'FS_CHMOD_FILE' ) ) { @chmod( $file, FS_CHMOD_FILE ); // @codingStandardsIgnoreLine. } } $resource = @fopen( $file, $mode ); // @codingStandardsIgnoreLine. if ( $resource ) { $this->handles[ $handle ] = $resource; return true; } } return false; } /** * Check if a handle is open. * * @param string $handle Log handle. * @return bool True if $handle is open. */ protected function is_open( $handle ) { return array_key_exists( $handle, $this->handles ) && is_resource( $this->handles[ $handle ] ); } /** * Close a handle. * * @param string $handle Log handle. * @return bool success */ protected function close( $handle ) { $result = false; if ( $this->is_open( $handle ) ) { $result = fclose( $this->handles[ $handle ] ); // @codingStandardsIgnoreLine. unset( $this->handles[ $handle ] ); } return $result; } /** * Add a log entry to chosen file. * * @param string $entry Log entry text. * @param string $handle Log entry handle. * * @return bool True if write was successful. */ protected function add( $entry, $handle ) { $result = false; if ( $this->should_rotate( $handle ) ) { $this->log_rotate( $handle ); } if ( $this->open( $handle ) && is_resource( $this->handles[ $handle ] ) ) { $result = fwrite( $this->handles[ $handle ], $entry . PHP_EOL ); // @codingStandardsIgnoreLine. } else { $this->cache_log( $entry, $handle ); } return false !== $result; } /** * Clear entries from chosen file. * * @param string $handle Log handle. * * @return bool */ public function clear( $handle ) { $result = false; // Close the file if it's already open. $this->close( $handle ); /** * $this->open( $handle, 'w' ) == Open the file for writing only. Place the file pointer at * the beginning of the file, and truncate the file to zero length. */ if ( $this->open( $handle, 'w' ) && is_resource( $this->handles[ $handle ] ) ) { $result = true; } do_action( 'kkart_log_clear', $handle ); return $result; } /** * Remove/delete the chosen file. * * @param string $handle Log handle. * * @return bool */ public function remove( $handle ) { $removed = false; $logs = $this->get_log_files(); $handle = sanitize_title( $handle ); if ( isset( $logs[ $handle ] ) && $logs[ $handle ] ) { $file = realpath( trailingslashit( KKART_LOG_DIR ) . $logs[ $handle ] ); if ( 0 === stripos( $file, realpath( trailingslashit( KKART_LOG_DIR ) ) ) && is_file( $file ) && is_writable( $file ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable $this->close( $file ); // Close first to be certain no processes keep it alive after it is unlinked. $removed = unlink( $file ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_unlink } do_action( 'kkart_log_remove', $handle, $removed ); } return $removed; } /** * Check if log file should be rotated. * * Compares the size of the log file to determine whether it is over the size limit. * * @param string $handle Log handle. * @return bool True if if should be rotated. */ protected function should_rotate( $handle ) { $file = self::get_log_file_path( $handle ); if ( $file ) { if ( $this->is_open( $handle ) ) { $file_stat = fstat( $this->handles[ $handle ] ); return $file_stat['size'] > $this->log_size_limit; } elseif ( file_exists( $file ) ) { return filesize( $file ) > $this->log_size_limit; } else { return false; } } else { return false; } } /** * Rotate log files. * * Logs are rotated by prepending '.x' to the '.log' suffix. * The current log plus 10 historical logs are maintained. * For example: * base.9.log -> [ REMOVED ] * base.8.log -> base.9.log * ... * base.0.log -> base.1.log * base.log -> base.0.log * * @param string $handle Log handle. */ protected function log_rotate( $handle ) { for ( $i = 8; $i >= 0; $i-- ) { $this->increment_log_infix( $handle, $i ); } $this->increment_log_infix( $handle ); } /** * Increment a log file suffix. * * @param string $handle Log handle. * @param null|int $number Optional. Default null. Log suffix number to be incremented. * @return bool True if increment was successful, otherwise false. */ protected function increment_log_infix( $handle, $number = null ) { if ( null === $number ) { $suffix = ''; $next_suffix = '.0'; } else { $suffix = '.' . $number; $next_suffix = '.' . ( $number + 1 ); } $rename_from = self::get_log_file_path( "{$handle}{$suffix}" ); $rename_to = self::get_log_file_path( "{$handle}{$next_suffix}" ); if ( $this->is_open( $rename_from ) ) { $this->close( $rename_from ); } if ( is_writable( $rename_from ) ) { // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_is_writable return rename( $rename_from, $rename_to ); // phpcs:ignore WordPress.VIP.FileSystemWritesDisallow.file_ops_rename } else { return false; } } /** * Get a log file path. * * @param string $handle Log name. * @return bool|string The log file path or false if path cannot be determined. */ public static function get_log_file_path( $handle ) { if ( function_exists( 'wp_hash' ) ) { return trailingslashit( KKART_LOG_DIR ) . self::get_log_file_name( $handle ); } else { kkart_doing_it_wrong( __METHOD__, __( 'This method should not be called before plugins_loaded.', 'kkart' ), '3.0' ); return false; } } /** * Get a log file name. * * File names consist of the handle, followed by the date, followed by a hash, .log. * * @since 3.3 * @param string $handle Log name. * @return bool|string The log file name or false if cannot be determined. */ public static function get_log_file_name( $handle ) { if ( function_exists( 'wp_hash' ) ) { $date_suffix = date( 'Y-m-d', time() ); $hash_suffix = wp_hash( $handle ); return sanitize_file_name( implode( '-', array( $handle, $date_suffix, $hash_suffix ) ) . '.log' ); } else { kkart_doing_it_wrong( __METHOD__, __( 'This method should not be called before plugins_loaded.', 'kkart' ), '3.3' ); return false; } } /** * Cache log to write later. * * @param string $entry Log entry text. * @param string $handle Log entry handle. */ protected function cache_log( $entry, $handle ) { $this->cached_logs[] = array( 'entry' => $entry, 'handle' => $handle, ); } /** * Write cached logs. */ public function write_cached_logs() { foreach ( $this->cached_logs as $log ) { $this->add( $log['entry'], $log['handle'] ); } } /** * Delete all logs older than a defined timestamp. * * @since 3.4.0 * @param integer $timestamp Timestamp to delete logs before. */ public static function delete_logs_before_timestamp( $timestamp = 0 ) { if ( ! $timestamp ) { return; } $log_files = self::get_log_files(); foreach ( $log_files as $log_file ) { $last_modified = filemtime( trailingslashit( KKART_LOG_DIR ) . $log_file ); if ( $last_modified < $timestamp ) { @unlink( trailingslashit( KKART_LOG_DIR ) . $log_file ); // @codingStandardsIgnoreLine. } } } /** * Get all log files in the log directory. * * @since 3.4.0 * @return array */ public static function get_log_files() { $files = @scandir( KKART_LOG_DIR ); // @codingStandardsIgnoreLine. $result = array(); if ( ! empty( $files ) ) { foreach ( $files as $key => $value ) { if ( ! in_array( $value, array( '.', '..' ), true ) ) { if ( ! is_dir( $value ) && strstr( $value, '.log' ) ) { $result[ sanitize_title( $value ) ] = $value; } } } } return $result; } } PK!xKkkart-update-functions.phpnu[get_results( "SELECT meta_value, meta_id, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_file_path' AND meta_value != '';" ); if ( $existing_file_paths ) { foreach ( $existing_file_paths as $existing_file_path ) { $old_file_path = trim( $existing_file_path->meta_value ); if ( ! empty( $old_file_path ) ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize $file_paths = serialize( array( md5( $old_file_path ) => $old_file_path ) ); $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_key = '_file_paths', meta_value = %s WHERE meta_id = %d", $file_paths, $existing_file_path->meta_id ) ); $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->prefix}kkart_downloadable_product_permissions SET download_id = %s WHERE product_id = %d", md5( $old_file_path ), $existing_file_path->post_id ) ); } } } } /** * Update permalinks for 2.0 * * @return void */ function kkart_update_200_permalinks() { // Setup default permalinks if shop page is defined. $permalinks = get_option( 'kkart_permalinks' ); $shop_page_id = kkart_get_page_id( 'shop' ); if ( empty( $permalinks ) && $shop_page_id > 0 ) { $base_slug = $shop_page_id > 0 && get_post( $shop_page_id ) ? get_page_uri( $shop_page_id ) : 'shop'; $category_base = 'yes' === get_option( 'kkart_prepend_shop_page_to_urls' ) ? trailingslashit( $base_slug ) : ''; $category_slug = get_option( 'kkart_product_category_slug' ) ? get_option( 'kkart_product_category_slug' ) : _x( 'product-category', 'slug', 'kkart' ); $tag_slug = get_option( 'kkart_product_tag_slug' ) ? get_option( 'kkart_product_tag_slug' ) : _x( 'product-tag', 'slug', 'kkart' ); if ( 'yes' === get_option( 'kkart_prepend_shop_page_to_products' ) ) { $product_base = trailingslashit( $base_slug ); } else { $product_slug = get_option( 'kkart_product_slug' ); if ( false !== $product_slug && ! empty( $product_slug ) ) { $product_base = trailingslashit( $product_slug ); } else { $product_base = trailingslashit( _x( 'product', 'slug', 'kkart' ) ); } } if ( 'yes' === get_option( 'kkart_prepend_category_to_products' ) ) { $product_base .= trailingslashit( '%product_cat%' ); } $permalinks = array( 'product_base' => untrailingslashit( $product_base ), 'category_base' => untrailingslashit( $category_base . $category_slug ), 'attribute_base' => untrailingslashit( $category_base ), 'tag_base' => untrailingslashit( $category_base . $tag_slug ), ); update_option( 'kkart_permalinks', $permalinks ); } } /** * Update sub-category display options for 2.0 * * @return void */ function kkart_update_200_subcat_display() { // Update subcat display settings. if ( 'yes' === get_option( 'kkart_shop_show_subcategories' ) ) { if ( 'yes' === get_option( 'kkart_hide_products_when_showing_subcategories' ) ) { update_option( 'kkart_shop_page_display', 'subcategories' ); } else { update_option( 'kkart_shop_page_display', 'both' ); } } if ( 'yes' === get_option( 'kkart_show_subcategories' ) ) { if ( 'yes' === get_option( 'kkart_hide_products_when_showing_subcategories' ) ) { update_option( 'kkart_category_archive_display', 'subcategories' ); } else { update_option( 'kkart_category_archive_display', 'both' ); } } } /** * Update tax rates for 2.0 * * @return void */ function kkart_update_200_taxrates() { global $wpdb; // Update tax rates. $loop = 0; $tax_rates = get_option( 'kkart_tax_rates' ); if ( $tax_rates ) { foreach ( $tax_rates as $tax_rate ) { foreach ( $tax_rate['countries'] as $country => $states ) { $states = array_reverse( $states ); foreach ( $states as $state ) { if ( '*' === $state ) { $state = ''; } $wpdb->insert( $wpdb->prefix . 'kkart_tax_rates', array( 'tax_rate_country' => $country, 'tax_rate_state' => $state, 'tax_rate' => $tax_rate['rate'], 'tax_rate_name' => $tax_rate['label'], 'tax_rate_priority' => 1, 'tax_rate_compound' => ( 'yes' === $tax_rate['compound'] ) ? 1 : 0, 'tax_rate_shipping' => ( 'yes' === $tax_rate['shipping'] ) ? 1 : 0, 'tax_rate_order' => $loop, 'tax_rate_class' => $tax_rate['class'], ) ); $loop++; } } } } $local_tax_rates = get_option( 'kkart_local_tax_rates' ); if ( $local_tax_rates ) { foreach ( $local_tax_rates as $tax_rate ) { $location_type = ( 'postcode' === $tax_rate['location_type'] ) ? 'postcode' : 'city'; if ( '*' === $tax_rate['state'] ) { $tax_rate['state'] = ''; } $wpdb->insert( $wpdb->prefix . 'kkart_tax_rates', array( 'tax_rate_country' => $tax_rate['country'], 'tax_rate_state' => $tax_rate['state'], 'tax_rate' => $tax_rate['rate'], 'tax_rate_name' => $tax_rate['label'], 'tax_rate_priority' => 2, 'tax_rate_compound' => ( 'yes' === $tax_rate['compound'] ) ? 1 : 0, 'tax_rate_shipping' => ( 'yes' === $tax_rate['shipping'] ) ? 1 : 0, 'tax_rate_order' => $loop, 'tax_rate_class' => $tax_rate['class'], ) ); $tax_rate_id = $wpdb->insert_id; if ( $tax_rate['locations'] ) { foreach ( $tax_rate['locations'] as $location ) { $wpdb->insert( $wpdb->prefix . 'kkart_tax_rate_locations', array( 'location_code' => $location, 'tax_rate_id' => $tax_rate_id, 'location_type' => $location_type, ) ); } } $loop++; } } update_option( 'kkart_tax_rates_backup', $tax_rates ); update_option( 'kkart_local_tax_rates_backup', $local_tax_rates ); delete_option( 'kkart_tax_rates' ); delete_option( 'kkart_local_tax_rates' ); } /** * Update order item line items for 2.0 * * @return void */ function kkart_update_200_line_items() { global $wpdb; // Now its time for the massive update to line items - move them to the new DB tables. // Reverse with UPDATE `wpkkart_postmeta` SET meta_key = '_order_items' WHERE meta_key = '_order_items_old'. $order_item_rows = $wpdb->get_results( "SELECT meta_value, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_order_items'" ); foreach ( $order_item_rows as $order_item_row ) { $order_items = (array) maybe_unserialize( $order_item_row->meta_value ); foreach ( $order_items as $order_item ) { if ( ! isset( $order_item['line_total'] ) && isset( $order_item['taxrate'] ) && isset( $order_item['cost'] ) ) { $order_item['line_tax'] = number_format( ( $order_item['cost'] * $order_item['qty'] ) * ( $order_item['taxrate'] / 100 ), 2, '.', '' ); $order_item['line_total'] = $order_item['cost'] * $order_item['qty']; $order_item['line_subtotal_tax'] = $order_item['line_tax']; $order_item['line_subtotal'] = $order_item['line_total']; } $order_item['line_tax'] = isset( $order_item['line_tax'] ) ? $order_item['line_tax'] : 0; $order_item['line_total'] = isset( $order_item['line_total'] ) ? $order_item['line_total'] : 0; $order_item['line_subtotal_tax'] = isset( $order_item['line_subtotal_tax'] ) ? $order_item['line_subtotal_tax'] : 0; $order_item['line_subtotal'] = isset( $order_item['line_subtotal'] ) ? $order_item['line_subtotal'] : 0; $item_id = kkart_add_order_item( $order_item_row->post_id, array( 'order_item_name' => $order_item['name'], 'order_item_type' => 'line_item', ) ); // Add line item meta. if ( $item_id ) { kkart_add_order_item_meta( $item_id, '_qty', absint( $order_item['qty'] ) ); kkart_add_order_item_meta( $item_id, '_tax_class', $order_item['tax_class'] ); kkart_add_order_item_meta( $item_id, '_product_id', $order_item['id'] ); kkart_add_order_item_meta( $item_id, '_variation_id', $order_item['variation_id'] ); kkart_add_order_item_meta( $item_id, '_line_subtotal', kkart_format_decimal( $order_item['line_subtotal'] ) ); kkart_add_order_item_meta( $item_id, '_line_subtotal_tax', kkart_format_decimal( $order_item['line_subtotal_tax'] ) ); kkart_add_order_item_meta( $item_id, '_line_total', kkart_format_decimal( $order_item['line_total'] ) ); kkart_add_order_item_meta( $item_id, '_line_tax', kkart_format_decimal( $order_item['line_tax'] ) ); $meta_rows = array(); // Insert meta. if ( ! empty( $order_item['item_meta'] ) ) { foreach ( $order_item['item_meta'] as $key => $meta ) { // Backwards compatibility. if ( is_array( $meta ) && isset( $meta['meta_name'] ) ) { $meta_rows[] = '(' . $item_id . ',"' . esc_sql( $meta['meta_name'] ) . '","' . esc_sql( $meta['meta_value'] ) . '")'; } else { $meta_rows[] = '(' . $item_id . ',"' . esc_sql( $key ) . '","' . esc_sql( $meta ) . '")'; } } } // Insert meta rows at once. if ( count( $meta_rows ) > 0 ) { $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->prefix}kkart_order_itemmeta ( order_item_id, meta_key, meta_value ) VALUES " . implode( ',', $meta_rows ) . ';', // @codingStandardsIgnoreLine $order_item_row->post_id ) ); } // Delete from DB (rename). $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_key = '_order_items_old' WHERE meta_key = '_order_items' AND post_id = %d", $order_item_row->post_id ) ); } unset( $meta_rows, $item_id, $order_item ); } } // Do the same kind of update for order_taxes - move to lines. // Reverse with UPDATE `wpkkart_postmeta` SET meta_key = '_order_taxes' WHERE meta_key = '_order_taxes_old'. $order_tax_rows = $wpdb->get_results( "SELECT meta_value, post_id FROM {$wpdb->postmeta} WHERE meta_key = '_order_taxes'" ); foreach ( $order_tax_rows as $order_tax_row ) { $order_taxes = (array) maybe_unserialize( $order_tax_row->meta_value ); if ( ! empty( $order_taxes ) ) { foreach ( $order_taxes as $order_tax ) { if ( ! isset( $order_tax['label'] ) || ! isset( $order_tax['cart_tax'] ) || ! isset( $order_tax['shipping_tax'] ) ) { continue; } $item_id = kkart_add_order_item( $order_tax_row->post_id, array( 'order_item_name' => $order_tax['label'], 'order_item_type' => 'tax', ) ); // Add line item meta. if ( $item_id ) { kkart_add_order_item_meta( $item_id, 'compound', absint( isset( $order_tax['compound'] ) ? $order_tax['compound'] : 0 ) ); kkart_add_order_item_meta( $item_id, 'tax_amount', kkart_clean( $order_tax['cart_tax'] ) ); kkart_add_order_item_meta( $item_id, 'shipping_tax_amount', kkart_clean( $order_tax['shipping_tax'] ) ); } // Delete from DB (rename). $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_key = '_order_taxes_old' WHERE meta_key = '_order_taxes' AND post_id = %d", $order_tax_row->post_id ) ); unset( $tax_amount ); } } } } /** * Update image settings for 2.0 * * @return void */ function kkart_update_200_images() { // Grab the pre 2.0 Image options and use to populate the new image options settings, // cleaning up afterwards like nice people do. foreach ( array( 'catalog', 'single', 'thumbnail' ) as $value ) { $old_settings = array_filter( array( 'width' => get_option( 'kkart_' . $value . '_image_width' ), 'height' => get_option( 'kkart_' . $value . '_image_height' ), 'crop' => get_option( 'kkart_' . $value . '_image_crop' ), ) ); if ( ! empty( $old_settings ) && update_option( 'shop_' . $value . '_image_size', $old_settings ) ) { delete_option( 'kkart_' . $value . '_image_width' ); delete_option( 'kkart_' . $value . '_image_height' ); delete_option( 'kkart_' . $value . '_image_crop' ); } } } /** * Update DB version for 2.0 * * @return void */ function kkart_update_200_db_version() { KKART_Install::update_db_version( '2.0.0' ); } /** * Update Brazilian States for 2.0.9 * * @return void */ function kkart_update_209_brazillian_state() { global $wpdb; // phpcs:disable WordPress.DB.SlowDBQuery // Update brazillian state codes. $wpdb->update( $wpdb->postmeta, array( 'meta_value' => 'BA', ), array( 'meta_key' => '_billing_state', 'meta_value' => 'BH', ) ); $wpdb->update( $wpdb->postmeta, array( 'meta_value' => 'BA', ), array( 'meta_key' => '_shipping_state', 'meta_value' => 'BH', ) ); $wpdb->update( $wpdb->usermeta, array( 'meta_value' => 'BA', ), array( 'meta_key' => 'billing_state', 'meta_value' => 'BH', ) ); $wpdb->update( $wpdb->usermeta, array( 'meta_value' => 'BA', ), array( 'meta_key' => 'shipping_state', 'meta_value' => 'BH', ) ); // phpcs:enable WordPress.DB.SlowDBQuery } /** * Update DB version for 2.0.9 * * @return void */ function kkart_update_209_db_version() { KKART_Install::update_db_version( '2.0.9' ); } /** * Remove pages for 2.1 * * @return void */ function kkart_update_210_remove_pages() { // Pages no longer used. wp_trash_post( get_option( 'kkart_pay_page_id' ) ); wp_trash_post( get_option( 'kkart_thanks_page_id' ) ); wp_trash_post( get_option( 'kkart_view_order_page_id' ) ); wp_trash_post( get_option( 'kkart_change_password_page_id' ) ); wp_trash_post( get_option( 'kkart_edit_address_page_id' ) ); wp_trash_post( get_option( 'kkart_lost_password_page_id' ) ); } /** * Update file paths to support multiple files for 2.1 * * @return void */ function kkart_update_210_file_paths() { global $wpdb; // Upgrade file paths to support multiple file paths + names etc. $existing_file_paths = $wpdb->get_results( "SELECT meta_value, meta_id FROM {$wpdb->postmeta} WHERE meta_key = '_file_paths' AND meta_value != '';" ); if ( $existing_file_paths ) { foreach ( $existing_file_paths as $existing_file_path ) { $needs_update = false; $new_value = array(); $value = maybe_unserialize( trim( $existing_file_path->meta_value ) ); if ( $value ) { foreach ( $value as $key => $file ) { if ( ! is_array( $file ) ) { $needs_update = true; $new_value[ $key ] = array( 'file' => $file, 'name' => kkart_get_filename_from_url( $file ), ); } else { $new_value[ $key ] = $file; } } if ( $needs_update ) { // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize $new_value = serialize( $new_value ); $wpdb->query( $wpdb->prepare( "UPDATE {$wpdb->postmeta} SET meta_key = %s, meta_value = %s WHERE meta_id = %d", '_downloadable_files', $new_value, $existing_file_path->meta_id ) ); } } } } } /** * Update DB version for 2.1 * * @return void */ function kkart_update_210_db_version() { KKART_Install::update_db_version( '2.1.0' ); } /** * Update shipping options for 2.2 * * @return void */ function kkart_update_220_shipping() { $kkart_ship_to_destination = 'shipping'; if ( get_option( 'kkart_ship_to_billing_address_only' ) === 'yes' ) { $kkart_ship_to_destination = 'billing_only'; } elseif ( get_option( 'kkart_ship_to_billing' ) === 'yes' ) { $kkart_ship_to_destination = 'billing'; } add_option( 'kkart_ship_to_destination', $kkart_ship_to_destination, '', 'no' ); } /** * Update order statuses for 2.2 * * @return void */ function kkart_update_220_order_status() { global $wpdb; $wpdb->query( "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) SET posts.post_status = 'kkart-pending' WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' AND term.slug LIKE 'pending%';" ); $wpdb->query( "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) SET posts.post_status = 'kkart-processing' WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' AND term.slug LIKE 'processing%';" ); $wpdb->query( "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) SET posts.post_status = 'kkart-on-hold' WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' AND term.slug LIKE 'on-hold%';" ); $wpdb->query( "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) SET posts.post_status = 'kkart-completed' WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' AND term.slug LIKE 'completed%';" ); $wpdb->query( "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) SET posts.post_status = 'kkart-cancelled' WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' AND term.slug LIKE 'cancelled%';" ); $wpdb->query( "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) SET posts.post_status = 'kkart-refunded' WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' AND term.slug LIKE 'refunded%';" ); $wpdb->query( "UPDATE {$wpdb->posts} as posts LEFT JOIN {$wpdb->term_relationships} AS rel ON posts.ID = rel.object_id LEFT JOIN {$wpdb->term_taxonomy} AS tax USING( term_taxonomy_id ) LEFT JOIN {$wpdb->terms} AS term USING( term_id ) SET posts.post_status = 'kkart-failed' WHERE posts.post_type = 'shop_order' AND posts.post_status = 'publish' AND tax.taxonomy = 'shop_order_status' AND term.slug LIKE 'failed%';" ); } /** * Update variations for 2.2 * * @return void */ function kkart_update_220_variations() { global $wpdb; // Update variations which manage stock. $update_variations = $wpdb->get_results( "SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock' LEFT OUTER JOIN {$wpdb->postmeta} as postmeta2 ON posts.ID = postmeta2.post_id AND postmeta2.meta_key = '_manage_stock' WHERE posts.post_type = 'product_variation' AND postmeta.meta_value IS NOT NULL AND postmeta.meta_value != '' AND postmeta2.meta_value IS NULL" ); foreach ( $update_variations as $variation ) { $parent_backorders = get_post_meta( $variation->variation_parent, '_backorders', true ); add_post_meta( $variation->variation_id, '_manage_stock', 'yes', true ); add_post_meta( $variation->variation_id, '_backorders', $parent_backorders ? $parent_backorders : 'no', true ); } } /** * Update attributes for 2.2 * * @return void */ function kkart_update_220_attributes() { global $wpdb; // Update taxonomy names with correct sanitized names. $attribute_taxonomies = $wpdb->get_results( 'SELECT attribute_name, attribute_id FROM ' . $wpdb->prefix . 'kkart_attribute_taxonomies' ); foreach ( $attribute_taxonomies as $attribute_taxonomy ) { $sanitized_attribute_name = kkart_sanitize_taxonomy_name( $attribute_taxonomy->attribute_name ); if ( $sanitized_attribute_name !== $attribute_taxonomy->attribute_name ) { if ( ! $wpdb->get_var( $wpdb->prepare( "SELECT 1=1 FROM {$wpdb->prefix}kkart_attribute_taxonomies WHERE attribute_name = %s;", $sanitized_attribute_name ) ) ) { // Update attribute. $wpdb->update( "{$wpdb->prefix}kkart_attribute_taxonomies", array( 'attribute_name' => $sanitized_attribute_name, ), array( 'attribute_id' => $attribute_taxonomy->attribute_id, ) ); // Update terms. $wpdb->update( $wpdb->term_taxonomy, array( 'taxonomy' => kkart_attribute_taxonomy_name( $sanitized_attribute_name ) ), array( 'taxonomy' => 'pa_' . $attribute_taxonomy->attribute_name ) ); } } } delete_transient( 'kkart_attribute_taxonomies' ); KKART_Cache_Helper::invalidate_cache_group( 'kkart-attributes' ); } /** * Update DB version for 2.2 * * @return void */ function kkart_update_220_db_version() { KKART_Install::update_db_version( '2.2.0' ); } /** * Update options for 2.3 * * @return void */ function kkart_update_230_options() { // _money_spent and _order_count may be out of sync - clear them delete_metadata( 'user', 0, '_money_spent', '', true ); delete_metadata( 'user', 0, '_order_count', '', true ); // To prevent taxes being hidden when using a default 'no address' in a store with tax inc prices, set the kkart_default_customer_address to use the store base address by default. if ( '' === get_option( 'kkart_default_customer_address', false ) && kkart_prices_include_tax() ) { update_option( 'kkart_default_customer_address', 'base' ); } } /** * Update DB version for 2.3 * * @return void */ function kkart_update_230_db_version() { KKART_Install::update_db_version( '2.3.0' ); } /** * Update calc discount options for 2.4 * * @return void */ function kkart_update_240_options() { /** * Coupon discount calculations. * Maintain the old coupon logic for upgrades. */ update_option( 'kkart_calc_discounts_sequentially', 'yes' ); } /** * Update shipping methods for 2.4 * * @return void */ function kkart_update_240_shipping_methods() { /** * Flat Rate Shipping. * Update legacy options to new math based options. */ $shipping_methods = array( 'kkart_flat_rates' => new KKART_Shipping_Legacy_Flat_Rate(), 'kkart_international_delivery_flat_rates' => new KKART_Shipping_Legacy_International_Delivery(), ); foreach ( $shipping_methods as $flat_rate_option_key => $shipping_method ) { // Stop this running more than once if routine is repeated. if ( version_compare( $shipping_method->get_option( 'version', 0 ), '2.4.0', '<' ) ) { $shipping_classes = KKART()->shipping()->get_shipping_classes(); $has_classes = count( $shipping_classes ) > 0; $cost_key = $has_classes ? 'no_class_cost' : 'cost'; $min_fee = $shipping_method->get_option( 'minimum_fee' ); $math_cost_strings = array( 'cost' => array(), 'no_class_cost' => array(), ); $math_cost_strings[ $cost_key ][] = $shipping_method->get_option( 'cost' ); $fee = $shipping_method->get_option( 'fee' ); if ( $fee ) { $math_cost_strings[ $cost_key ][] = strstr( $fee, '%' ) ? '[fee percent="' . str_replace( '%', '', $fee ) . '" min="' . esc_attr( $min_fee ) . '"]' : $fee; } foreach ( $shipping_classes as $shipping_class ) { $rate_key = 'class_cost_' . $shipping_class->slug; $math_cost_strings[ $rate_key ] = $math_cost_strings['no_class_cost']; } $flat_rates = array_filter( (array) get_option( $flat_rate_option_key, array() ) ); if ( $flat_rates ) { foreach ( $flat_rates as $shipping_class => $rate ) { $rate_key = 'class_cost_' . $shipping_class; if ( $rate['cost'] || $rate['fee'] ) { $math_cost_strings[ $rate_key ][] = $rate['cost']; $math_cost_strings[ $rate_key ][] = strstr( $rate['fee'], '%' ) ? '[fee percent="' . str_replace( '%', '', $rate['fee'] ) . '" min="' . esc_attr( $min_fee ) . '"]' : $rate['fee']; } } } if ( 'item' === $shipping_method->type ) { foreach ( $math_cost_strings as $key => $math_cost_string ) { $math_cost_strings[ $key ] = array_filter( array_map( 'trim', $math_cost_strings[ $key ] ) ); if ( ! empty( $math_cost_strings[ $key ] ) ) { $last_key = max( 0, count( $math_cost_strings[ $key ] ) - 1 ); $math_cost_strings[ $key ][0] = '( ' . $math_cost_strings[ $key ][0]; $math_cost_strings[ $key ][ $last_key ] .= ' ) * [qty]'; } } } $math_cost_strings['cost'][] = $shipping_method->get_option( 'cost_per_order' ); // Save settings. foreach ( $math_cost_strings as $option_id => $math_cost_string ) { $shipping_method->settings[ $option_id ] = implode( ' + ', array_filter( $math_cost_string ) ); } $shipping_method->settings['version'] = '2.4.0'; $shipping_method->settings['type'] = 'item' === $shipping_method->settings['type'] ? 'class' : $shipping_method->settings['type']; update_option( $shipping_method->plugin_id . $shipping_method->id . '_settings', $shipping_method->settings ); } } } /** * Update API keys for 2.4 * * @return void */ function kkart_update_240_api_keys() { global $wpdb; /** * Update the old user API keys to the new Apps keys. */ $api_users = $wpdb->get_results( "SELECT user_id FROM $wpdb->usermeta WHERE meta_key = 'kkart_api_consumer_key'" ); $apps_keys = array(); // Get user data. foreach ( $api_users as $_user ) { $user = get_userdata( $_user->user_id ); $apps_keys[] = array( 'user_id' => $user->ID, 'permissions' => $user->kkart_api_key_permissions, 'consumer_key' => kkart_api_hash( $user->kkart_api_consumer_key ), 'consumer_secret' => $user->kkart_api_consumer_secret, 'truncated_key' => substr( $user->kkart_api_consumer_secret, -7 ), ); } if ( ! empty( $apps_keys ) ) { // Create new apps. foreach ( $apps_keys as $app ) { $wpdb->insert( $wpdb->prefix . 'kkart_api_keys', $app, array( '%d', '%s', '%s', '%s', '%s', ) ); } // Delete old user keys from usermeta. foreach ( $api_users as $_user ) { $user_id = intval( $_user->user_id ); delete_user_meta( $user_id, 'kkart_api_consumer_key' ); delete_user_meta( $user_id, 'kkart_api_consumer_secret' ); delete_user_meta( $user_id, 'kkart_api_key_permissions' ); } } } /** * Update webhooks for 2.4 * * @return void */ function kkart_update_240_webhooks() { // phpcs:disable WordPress.DB.SlowDBQuery /** * Webhooks. * Make sure order.update webhooks get the kkart_order_edit_status hook. */ $order_update_webhooks = get_posts( array( 'posts_per_page' => -1, 'post_type' => 'shop_webhook', 'meta_key' => '_topic', 'meta_value' => 'order.updated', ) ); foreach ( $order_update_webhooks as $order_update_webhook ) { $webhook = new KKART_Webhook( $order_update_webhook->ID ); $webhook->set_topic( 'order.updated' ); } // phpcs:enable WordPress.DB.SlowDBQuery } /** * Update refunds for 2.4 * * @return void */ function kkart_update_240_refunds() { global $wpdb; /** * Refunds for full refunded orders. * Update fully refunded orders to ensure they have a refund line item so reports add up. */ $refunded_orders = get_posts( array( 'posts_per_page' => -1, 'post_type' => 'shop_order', 'post_status' => array( 'kkart-refunded' ), ) ); // Ensure emails are disabled during this update routine. remove_all_actions( 'kkart_order_status_refunded_notification' ); remove_all_actions( 'kkart_order_partially_refunded_notification' ); remove_action( 'kkart_order_status_refunded', array( 'KKART_Emails', 'send_transactional_email' ) ); remove_action( 'kkart_order_partially_refunded', array( 'KKART_Emails', 'send_transactional_email' ) ); foreach ( $refunded_orders as $refunded_order ) { $order_total = get_post_meta( $refunded_order->ID, '_order_total', true ); $refunded_total = $wpdb->get_var( $wpdb->prepare( "SELECT SUM( postmeta.meta_value ) FROM $wpdb->postmeta AS postmeta INNER JOIN $wpdb->posts AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d ) WHERE postmeta.meta_key = '_refund_amount' AND postmeta.post_id = posts.ID", $refunded_order->ID ) ); if ( $order_total > $refunded_total ) { kkart_create_refund( array( 'amount' => $order_total - $refunded_total, 'reason' => __( 'Order fully refunded', 'kkart' ), 'order_id' => $refunded_order->ID, 'line_items' => array(), 'date' => $refunded_order->post_modified, ) ); } } kkart_delete_shop_order_transients(); } /** * Update DB version for 2.4 * * @return void */ function kkart_update_240_db_version() { KKART_Install::update_db_version( '2.4.0' ); } /** * Update variations for 2.4.1 * * @return void */ function kkart_update_241_variations() { global $wpdb; // Select variations that don't have any _stock_status implemented on Kkart 2.2. $update_variations = $wpdb->get_results( "SELECT DISTINCT posts.ID AS variation_id, posts.post_parent AS variation_parent FROM {$wpdb->posts} as posts LEFT OUTER JOIN {$wpdb->postmeta} AS postmeta ON posts.ID = postmeta.post_id AND postmeta.meta_key = '_stock_status' WHERE posts.post_type = 'product_variation' AND postmeta.meta_value IS NULL" ); foreach ( $update_variations as $variation ) { // Get the parent _stock_status. $parent_stock_status = get_post_meta( $variation->variation_parent, '_stock_status', true ); // Set the _stock_status. add_post_meta( $variation->variation_id, '_stock_status', $parent_stock_status ? $parent_stock_status : 'instock', true ); // Delete old product children array. delete_transient( 'kkart_product_children_' . $variation->variation_parent ); } // Invalidate old transients such as kkart_var_price. KKART_Cache_Helper::get_transient_version( 'product', true ); } /** * Update DB version for 2.4.1 * * @return void */ function kkart_update_241_db_version() { KKART_Install::update_db_version( '2.4.1' ); } /** * Update currency settings for 2.5 * * @return void */ function kkart_update_250_currency() { global $wpdb; // Fix currency settings for LAK currency. $current_currency = get_option( 'kkart_currency' ); if ( 'KIP' === $current_currency ) { update_option( 'kkart_currency', 'LAK' ); } // phpcs:disable WordPress.DB.SlowDBQuery // Update LAK currency code. $wpdb->update( $wpdb->postmeta, array( 'meta_value' => 'LAK', ), array( 'meta_key' => '_order_currency', 'meta_value' => 'KIP', ) ); // phpcs:enable WordPress.DB.SlowDBQuery } /** * Update DB version for 2.5 * * @return void */ function kkart_update_250_db_version() { KKART_Install::update_db_version( '2.5.0' ); } /** * Update ship to countries options for 2.6 * * @return void */ function kkart_update_260_options() { // kkart_calc_shipping option has been removed in 2.6. if ( 'no' === get_option( 'kkart_calc_shipping' ) ) { update_option( 'kkart_ship_to_countries', 'disabled' ); } KKART_Admin_Notices::add_notice( 'legacy_shipping' ); } /** * Update term meta for 2.6 * * @return void */ function kkart_update_260_termmeta() { global $wpdb; /** * Migrate term meta to WordPress tables. */ if ( get_option( 'db_version' ) >= 34370 && $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}kkart_termmeta';" ) ) { if ( $wpdb->query( "INSERT INTO {$wpdb->termmeta} ( term_id, meta_key, meta_value ) SELECT kkart_term_id, meta_key, meta_value FROM {$wpdb->prefix}kkart_termmeta;" ) ) { $wpdb->query( "DROP TABLE IF EXISTS {$wpdb->prefix}kkart_termmeta" ); wp_cache_flush(); } } } /** * Update zones for 2.6 * * @return void */ function kkart_update_260_zones() { global $wpdb; /** * Old (table rate) shipping zones to new core shipping zones migration. * zone_enabled and zone_type are no longer used, but it's safe to leave them be. */ if ( $wpdb->get_var( "SHOW COLUMNS FROM `{$wpdb->prefix}kkart_shipping_zones` LIKE 'zone_enabled';" ) ) { $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_shipping_zones CHANGE `zone_type` `zone_type` VARCHAR(40) NOT NULL DEFAULT '';" ); $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_shipping_zones CHANGE `zone_enabled` `zone_enabled` INT(1) NOT NULL DEFAULT 1;" ); } } /** * Update zone methods for 2.6 * * @return void */ function kkart_update_260_zone_methods() { global $wpdb; /** * Shipping zones in KKART 2.6.0 use a table named kkart_shipping_zone_methods. * Migrate the old data out of kkart_shipping_zone_shipping_methods into the new table and port over any known options (used by table rates and flat rate boxes). */ if ( $wpdb->get_var( "SHOW TABLES LIKE '{$wpdb->prefix}kkart_shipping_zone_shipping_methods';" ) ) { $old_methods = $wpdb->get_results( "SELECT zone_id, shipping_method_type, shipping_method_order, shipping_method_id FROM {$wpdb->prefix}kkart_shipping_zone_shipping_methods;" ); if ( $old_methods ) { $max_new_id = $wpdb->get_var( "SELECT MAX(instance_id) FROM {$wpdb->prefix}kkart_shipping_zone_methods" ); $max_old_id = $wpdb->get_var( "SELECT MAX(shipping_method_id) FROM {$wpdb->prefix}kkart_shipping_zone_shipping_methods" ); // Avoid ID conflicts. $wpdb->query( $wpdb->prepare( "ALTER TABLE {$wpdb->prefix}kkart_shipping_zone_methods AUTO_INCREMENT = %d;", max( $max_new_id, $max_old_id ) + 1 ) ); // Store changes. $changes = array(); // Move data. foreach ( $old_methods as $old_method ) { $wpdb->insert( $wpdb->prefix . 'kkart_shipping_zone_methods', array( 'zone_id' => $old_method->zone_id, 'method_id' => $old_method->shipping_method_type, 'method_order' => $old_method->shipping_method_order, ) ); $new_instance_id = $wpdb->insert_id; // Move main settings. $older_settings_key = 'kkart_' . $old_method->shipping_method_type . '-' . $old_method->shipping_method_id . '_settings'; $old_settings_key = 'kkart_' . $old_method->shipping_method_type . '_' . $old_method->shipping_method_id . '_settings'; add_option( 'kkart_' . $old_method->shipping_method_type . '_' . $new_instance_id . '_settings', get_option( $old_settings_key, get_option( $older_settings_key ) ) ); // Handling for table rate and flat rate box shipping. if ( 'table_rate' === $old_method->shipping_method_type ) { // Move priority settings. add_option( 'kkart_table_rate_default_priority_' . $new_instance_id, get_option( 'kkart_table_rate_default_priority_' . $old_method->shipping_method_id ) ); add_option( 'kkart_table_rate_priorities_' . $new_instance_id, get_option( 'kkart_table_rate_priorities_' . $old_method->shipping_method_id ) ); // Move rates. $wpdb->update( $wpdb->prefix . 'kkart_shipping_table_rates', array( 'shipping_method_id' => $new_instance_id, ), array( 'shipping_method_id' => $old_method->shipping_method_id, ) ); } elseif ( 'flat_rate_boxes' === $old_method->shipping_method_type ) { $wpdb->update( $wpdb->prefix . 'kkart_shipping_flat_rate_boxes', array( 'shipping_method_id' => $new_instance_id, ), array( 'shipping_method_id' => $old_method->shipping_method_id, ) ); } $changes[ $old_method->shipping_method_id ] = $new_instance_id; } // $changes contains keys (old method ids) and values (new instance ids) if extra processing is needed in plugins. // Store this to an option so extensions can pick it up later, then fire an action. update_option( 'kkart_updated_instance_ids', $changes ); do_action( 'kkart_updated_instance_ids', $changes ); } } // Change ranges used to ... $wpdb->query( "UPDATE {$wpdb->prefix}kkart_shipping_zone_locations SET location_code = REPLACE( location_code, '-', '...' );" ); } /** * Update refunds for 2.6 * * @return void */ function kkart_update_260_refunds() { global $wpdb; /** * Refund item qty should be negative. */ $wpdb->query( "UPDATE {$wpdb->prefix}kkart_order_itemmeta as item_meta LEFT JOIN {$wpdb->prefix}kkart_order_items as items ON item_meta.order_item_id = items.order_item_id LEFT JOIN {$wpdb->posts} as posts ON items.order_id = posts.ID SET item_meta.meta_value = item_meta.meta_value * -1 WHERE item_meta.meta_value > 0 AND item_meta.meta_key = '_qty' AND posts.post_type = 'shop_order_refund'" ); } /** * Update DB version for 2.6 * * @return void */ function kkart_update_260_db_version() { KKART_Install::update_db_version( '2.6.0' ); } /** * Update webhooks for 3.0 * * @return void */ function kkart_update_300_webhooks() { // phpcs:disable WordPress.DB.SlowDBQuery /** * Make sure product.update webhooks get the kkart_product_quick_edit_save * and kkart_product_bulk_edit_save hooks. */ $product_update_webhooks = get_posts( array( 'posts_per_page' => -1, 'post_type' => 'shop_webhook', 'meta_key' => '_topic', 'meta_value' => 'product.updated', ) ); foreach ( $product_update_webhooks as $product_update_webhook ) { $webhook = new KKART_Webhook( $product_update_webhook->ID ); $webhook->set_topic( 'product.updated' ); } // phpcs:enable WordPress.DB.SlowDBQuery } /** * Add an index to the field comment_type to improve the response time of the query * used by KKART_Comments::wp_count_comments() to get the number of comments by type. */ function kkart_update_300_comment_type_index() { global $wpdb; $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->comments} WHERE column_name = 'comment_type' and key_name = 'woo_idx_comment_type'" ); if ( is_null( $index_exists ) ) { // Add an index to the field comment_type to improve the response time of the query // used by KKART_Comments::wp_count_comments() to get the number of comments by type. $wpdb->query( "ALTER TABLE {$wpdb->comments} ADD INDEX woo_idx_comment_type (comment_type)" ); } } /** * Update grouped products for 3.0 * * @return void */ function kkart_update_300_grouped_products() { global $wpdb; $parents = $wpdb->get_col( "SELECT DISTINCT( post_parent ) FROM {$wpdb->posts} WHERE post_parent > 0 AND post_type = 'product';" ); foreach ( $parents as $parent_id ) { $parent = kkart_get_product( $parent_id ); if ( $parent && $parent->is_type( 'grouped' ) ) { $children_ids = get_posts( array( 'post_parent' => $parent_id, 'posts_per_page' => -1, 'post_type' => 'product', 'fields' => 'ids', ) ); update_post_meta( $parent_id, '_children', $children_ids ); // Update children to remove the parent. $wpdb->update( $wpdb->posts, array( 'post_parent' => 0, ), array( 'post_parent' => $parent_id, ) ); } } } /** * Update shipping tax classes for 3.0 * * @return void */ function kkart_update_300_settings() { $kkart_shipping_tax_class = get_option( 'kkart_shipping_tax_class' ); if ( '' === $kkart_shipping_tax_class ) { update_option( 'kkart_shipping_tax_class', 'inherit' ); } elseif ( 'standard' === $kkart_shipping_tax_class ) { update_option( 'kkart_shipping_tax_class', '' ); } } /** * Convert meta values into term for product visibility. */ function kkart_update_300_product_visibility() { global $wpdb; KKART_Install::create_terms(); $featured_term = get_term_by( 'name', 'featured', 'product_visibility' ); if ( $featured_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_featured' AND meta_value = 'yes';", $featured_term->term_taxonomy_id ) ); } $exclude_search_term = get_term_by( 'name', 'exclude-from-search', 'product_visibility' ); if ( $exclude_search_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'catalog');", $exclude_search_term->term_taxonomy_id ) ); } $exclude_catalog_term = get_term_by( 'name', 'exclude-from-catalog', 'product_visibility' ); if ( $exclude_catalog_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_visibility' AND meta_value IN ('hidden', 'search');", $exclude_catalog_term->term_taxonomy_id ) ); } $outofstock_term = get_term_by( 'name', 'outofstock', 'product_visibility' ); if ( $outofstock_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_stock_status' AND meta_value = 'outofstock';", $outofstock_term->term_taxonomy_id ) ); } $rating_term = get_term_by( 'name', 'rated-1', 'product_visibility' ); if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_kkart_average_rating' AND ROUND( meta_value ) = 1;", $rating_term->term_taxonomy_id ) ); } $rating_term = get_term_by( 'name', 'rated-2', 'product_visibility' ); if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_kkart_average_rating' AND ROUND( meta_value ) = 2;", $rating_term->term_taxonomy_id ) ); } $rating_term = get_term_by( 'name', 'rated-3', 'product_visibility' ); if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_kkart_average_rating' AND ROUND( meta_value ) = 3;", $rating_term->term_taxonomy_id ) ); } $rating_term = get_term_by( 'name', 'rated-4', 'product_visibility' ); if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_kkart_average_rating' AND ROUND( meta_value ) = 4;", $rating_term->term_taxonomy_id ) ); } $rating_term = get_term_by( 'name', 'rated-5', 'product_visibility' ); if ( $rating_term ) { $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO {$wpdb->term_relationships} SELECT post_id, %d, 0 FROM {$wpdb->postmeta} WHERE meta_key = '_kkart_average_rating' AND ROUND( meta_value ) = 5;", $rating_term->term_taxonomy_id ) ); } } /** * Update DB Version. */ function kkart_update_300_db_version() { KKART_Install::update_db_version( '3.0.0' ); } /** * Add an index to the downloadable product permissions table to improve performance of update_user_by_order_id. */ function kkart_update_310_downloadable_products() { global $wpdb; $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}kkart_downloadable_product_permissions WHERE column_name = 'order_id' and key_name = 'order_id'" ); if ( is_null( $index_exists ) ) { $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_downloadable_product_permissions ADD INDEX order_id (order_id)" ); } } /** * Find old order notes and ensure they have the correct type for exclusion. */ function kkart_update_310_old_comments() { global $wpdb; $wpdb->query( "UPDATE $wpdb->comments comments LEFT JOIN $wpdb->posts as posts ON comments.comment_post_ID = posts.ID SET comment_type = 'order_note' WHERE posts.post_type = 'shop_order' AND comment_type = '';" ); } /** * Update DB Version. */ function kkart_update_310_db_version() { KKART_Install::update_db_version( '3.1.0' ); } /** * Update shop_manager capabilities. */ function kkart_update_312_shop_manager_capabilities() { $role = get_role( 'shop_manager' ); $role->remove_cap( 'unfiltered_html' ); } /** * Update DB Version. */ function kkart_update_312_db_version() { KKART_Install::update_db_version( '3.1.2' ); } /** * Update state codes for Mexico. */ function kkart_update_320_mexican_states() { global $wpdb; $mx_states = array( 'Distrito Federal' => 'CMX', 'Jalisco' => 'JAL', 'Nuevo Leon' => 'NLE', 'Aguascalientes' => 'AGS', 'Baja California' => 'BCN', 'Baja California Sur' => 'BCS', 'Campeche' => 'CAM', 'Chiapas' => 'CHP', 'Chihuahua' => 'CHH', 'Coahuila' => 'COA', 'Colima' => 'COL', 'Durango' => 'DGO', 'Guanajuato' => 'GTO', 'Guerrero' => 'GRO', 'Hidalgo' => 'HGO', 'Estado de Mexico' => 'MEX', 'Michoacan' => 'MIC', 'Morelos' => 'MOR', 'Nayarit' => 'NAY', 'Oaxaca' => 'OAX', 'Puebla' => 'PUE', 'Queretaro' => 'QRO', 'Quintana Roo' => 'ROO', 'San Luis Potosi' => 'SLP', 'Sinaloa' => 'SIN', 'Sonora' => 'SON', 'Tabasco' => 'TAB', 'Tamaulipas' => 'TMP', 'Tlaxcala' => 'TLA', 'Veracruz' => 'VER', 'Yucatan' => 'YUC', 'Zacatecas' => 'ZAC', ); foreach ( $mx_states as $old => $new ) { $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_value = %s WHERE meta_key IN ( '_billing_state', '_shipping_state' ) AND meta_value = %s", $new, $old ) ); $wpdb->update( "{$wpdb->prefix}kkart_shipping_zone_locations", array( 'location_code' => 'MX:' . $new, ), array( 'location_code' => 'MX:' . $old, ) ); $wpdb->update( "{$wpdb->prefix}kkart_tax_rates", array( 'tax_rate_state' => strtoupper( $new ), ), array( 'tax_rate_state' => strtoupper( $old ), ) ); } } /** * Update DB Version. */ function kkart_update_320_db_version() { KKART_Install::update_db_version( '3.2.0' ); } /** * Update image settings to use new aspect ratios and widths. */ function kkart_update_330_image_options() { $old_thumbnail_size = get_option( 'shop_catalog_image_size', array() ); $old_single_size = get_option( 'shop_single_image_size', array() ); if ( ! empty( $old_thumbnail_size['width'] ) ) { $width = absint( $old_thumbnail_size['width'] ); $height = absint( $old_thumbnail_size['height'] ); $hard_crop = ! empty( $old_thumbnail_size['crop'] ); if ( ! $width ) { $width = 300; } if ( ! $height ) { $height = $width; } update_option( 'kkart_thumbnail_image_width', $width ); // Calculate cropping mode from old image options. if ( ! $hard_crop ) { update_option( 'kkart_thumbnail_cropping', 'uncropped' ); } elseif ( $width === $height ) { update_option( 'kkart_thumbnail_cropping', '1:1' ); } else { $ratio = $width / $height; $fraction = kkart_decimal_to_fraction( $ratio ); if ( $fraction ) { update_option( 'kkart_thumbnail_cropping', 'custom' ); update_option( 'kkart_thumbnail_cropping_custom_width', $fraction[0] ); update_option( 'kkart_thumbnail_cropping_custom_height', $fraction[1] ); } } } // Single is uncropped. if ( ! empty( $old_single_size['width'] ) ) { update_option( 'kkart_single_image_width', absint( $old_single_size['width'] ) ); } } /** * Migrate webhooks from post type to CRUD. */ function kkart_update_330_webhooks() { register_post_type( 'shop_webhook' ); // Map statuses from post_type to Webhooks CRUD. $statuses = array( 'publish' => 'active', 'draft' => 'paused', 'pending' => 'disabled', ); $posts = get_posts( array( 'posts_per_page' => -1, 'post_type' => 'shop_webhook', 'post_status' => 'any', ) ); foreach ( $posts as $post ) { $webhook = new KKART_Webhook(); $webhook->set_name( $post->post_title ); $webhook->set_status( isset( $statuses[ $post->post_status ] ) ? $statuses[ $post->post_status ] : 'disabled' ); $webhook->set_delivery_url( get_post_meta( $post->ID, '_delivery_url', true ) ); $webhook->set_secret( get_post_meta( $post->ID, '_secret', true ) ); $webhook->set_topic( get_post_meta( $post->ID, '_topic', true ) ); $webhook->set_api_version( get_post_meta( $post->ID, '_api_version', true ) ); $webhook->set_user_id( $post->post_author ); $webhook->set_pending_delivery( false ); $webhook->save(); wp_delete_post( $post->ID, true ); } unregister_post_type( 'shop_webhook' ); } /** * Assign default cat to all products with no cats. */ function kkart_update_330_set_default_product_cat() { global $wpdb; $default_category = get_option( 'default_product_cat', 0 ); if ( $default_category ) { $wpdb->query( $wpdb->prepare( "INSERT INTO {$wpdb->term_relationships} (object_id, term_taxonomy_id) SELECT DISTINCT posts.ID, %s FROM {$wpdb->posts} posts LEFT JOIN ( SELECT object_id FROM {$wpdb->term_relationships} term_relationships LEFT JOIN {$wpdb->term_taxonomy} term_taxonomy ON term_relationships.term_taxonomy_id = term_taxonomy.term_taxonomy_id WHERE term_taxonomy.taxonomy = 'product_cat' ) AS tax_query ON posts.ID = tax_query.object_id WHERE posts.post_type = 'product' AND tax_query.object_id IS NULL", $default_category ) ); wp_cache_flush(); delete_transient( 'kkart_term_counts' ); wp_update_term_count_now( array( $default_category ), 'product_cat' ); } } /** * Update product stock status to use the new onbackorder status. */ function kkart_update_330_product_stock_status() { global $wpdb; if ( 'yes' !== get_option( 'kkart_manage_stock' ) ) { return; } $min_stock_amount = (int) get_option( 'kkart_notify_no_stock_amount', 0 ); // Get all products that have stock management enabled, stock less than or equal to min stock amount, and backorders enabled. $post_ids = $wpdb->get_col( $wpdb->prepare( "SELECT t1.post_id FROM $wpdb->postmeta t1 INNER JOIN $wpdb->postmeta t2 ON t1.post_id = t2.post_id AND t1.meta_key = '_manage_stock' AND t1.meta_value = 'yes' AND t2.meta_key = '_stock' AND t2.meta_value <= %d INNER JOIN $wpdb->postmeta t3 ON t2.post_id = t3.post_id AND t3.meta_key = '_backorders' AND ( t3.meta_value = 'yes' OR t3.meta_value = 'notify' )", $min_stock_amount ) ); if ( empty( $post_ids ) ) { return; } $post_ids = array_map( 'absint', $post_ids ); // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared // Set the status to onbackorder for those products. $wpdb->query( "UPDATE $wpdb->postmeta SET meta_value = 'onbackorder' WHERE meta_key = '_stock_status' AND post_id IN ( " . implode( ',', $post_ids ) . ' )' ); // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared } /** * Clear addons page transients */ function kkart_update_330_clear_transients() { delete_transient( 'kkart_addons_sections' ); delete_transient( 'kkart_addons_featured' ); } /** * Set PayPal's sandbox credentials. */ function kkart_update_330_set_paypal_sandbox_credentials() { $paypal_settings = get_option( 'kkart_paypal_settings' ); if ( isset( $paypal_settings['testmode'] ) && 'yes' === $paypal_settings['testmode'] ) { foreach ( array( 'api_username', 'api_password', 'api_signature' ) as $credential ) { if ( ! empty( $paypal_settings[ $credential ] ) ) { $paypal_settings[ 'sandbox_' . $credential ] = $paypal_settings[ $credential ]; } } update_option( 'kkart_paypal_settings', $paypal_settings ); } } /** * Update DB Version. */ function kkart_update_330_db_version() { KKART_Install::update_db_version( '3.3.0' ); } /** * Update state codes for Ireland and BD. */ function kkart_update_340_states() { $country_states = array( 'IE' => array( 'CK' => 'CO', 'DN' => 'D', 'GY' => 'G', 'TY' => 'TA', ), 'BD' => array( 'BAG' => 'BD-05', 'BAN' => 'BD-01', 'BAR' => 'BD-02', 'BARI' => 'BD-06', 'BHO' => 'BD-07', 'BOG' => 'BD-03', 'BRA' => 'BD-04', 'CHA' => 'BD-09', 'CHI' => 'BD-10', 'CHU' => 'BD-12', 'COX' => 'BD-11', 'COM' => 'BD-08', 'DHA' => 'BD-13', 'DIN' => 'BD-14', 'FAR' => 'BD-15', 'FEN' => 'BD-16', 'GAI' => 'BD-19', 'GAZI' => 'BD-18', 'GOP' => 'BD-17', 'HAB' => 'BD-20', 'JAM' => 'BD-21', 'JES' => 'BD-22', 'JHA' => 'BD-25', 'JHE' => 'BD-23', 'JOY' => 'BD-24', 'KHA' => 'BD-29', 'KHU' => 'BD-27', 'KIS' => 'BD-26', 'KUR' => 'BD-28', 'KUS' => 'BD-30', 'LAK' => 'BD-31', 'LAL' => 'BD-32', 'MAD' => 'BD-36', 'MAG' => 'BD-37', 'MAN' => 'BD-33', 'MEH' => 'BD-39', 'MOU' => 'BD-38', 'MUN' => 'BD-35', 'MYM' => 'BD-34', 'NAO' => 'BD-48', 'NAR' => 'BD-43', 'NARG' => 'BD-40', 'NARD' => 'BD-42', 'NAT' => 'BD-44', 'NAW' => 'BD-45', 'NET' => 'BD-41', 'NIL' => 'BD-46', 'NOA' => 'BD-47', 'PAB' => 'BD-49', 'PAN' => 'BD-52', 'PAT' => 'BD-51', 'PIR' => 'BD-50', 'RAJB' => 'BD-53', 'RAJ' => 'BD-54', 'RAN' => 'BD-56', 'RANP' => 'BD-55', 'SAT' => 'BD-58', 'SHA' => 'BD-57', 'SIR' => 'BD-59', 'SUN' => 'BD-61', 'SYL' => 'BD-60', 'TAN' => 'BD-63', 'THA' => 'BD-64', ), ); update_option( 'kkart_update_340_states', $country_states ); } /** * Update next state in the queue. * * @return bool True to run again, false if completed. */ function kkart_update_340_state() { global $wpdb; $country_states = array_filter( (array) get_option( 'kkart_update_340_states', array() ) ); if ( empty( $country_states ) ) { return false; } foreach ( $country_states as $country => $states ) { foreach ( $states as $old => $new ) { $wpdb->query( $wpdb->prepare( "UPDATE $wpdb->postmeta SET meta_value = %s WHERE meta_key IN ( '_billing_state', '_shipping_state' ) AND meta_value = %s", $new, $old ) ); $wpdb->update( "{$wpdb->prefix}kkart_shipping_zone_locations", array( 'location_code' => $country . ':' . $new, ), array( 'location_code' => $country . ':' . $old, ) ); $wpdb->update( "{$wpdb->prefix}kkart_tax_rates", array( 'tax_rate_state' => strtoupper( $new ), ), array( 'tax_rate_state' => strtoupper( $old ), ) ); unset( $country_states[ $country ][ $old ] ); if ( empty( $country_states[ $country ] ) ) { unset( $country_states[ $country ] ); } break 2; } } if ( ! empty( $country_states ) ) { return update_option( 'kkart_update_340_states', $country_states ); } delete_option( 'kkart_update_340_states' ); return false; } /** * Set last active prop for users. */ function kkart_update_340_last_active() { global $wpdb; // @codingStandardsIgnoreStart. $wpdb->query( $wpdb->prepare( " INSERT INTO {$wpdb->usermeta} (user_id, meta_key, meta_value) SELECT DISTINCT users.ID, 'kkart_last_active', %s FROM {$wpdb->users} as users LEFT OUTER JOIN {$wpdb->usermeta} AS usermeta ON users.ID = usermeta.user_id AND usermeta.meta_key = 'kkart_last_active' WHERE usermeta.meta_value IS NULL ", (string) strtotime( date( 'Y-m-d', current_time( 'timestamp', true ) ) ) ) ); // @codingStandardsIgnoreEnd. } /** * Update DB Version. */ function kkart_update_340_db_version() { KKART_Install::update_db_version( '3.4.0' ); } /** * Remove duplicate foreign keys * * @return void */ function kkart_update_343_cleanup_foreign_keys() { global $wpdb; $results = $wpdb->get_results( "SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = '{$wpdb->dbname}' AND CONSTRAINT_NAME LIKE '%kkart_download_log_ib%' AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = '{$wpdb->prefix}kkart_download_log'" ); if ( $results ) { foreach ( $results as $fk ) { $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_download_log DROP FOREIGN KEY {$fk->CONSTRAINT_NAME}" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared } } } /** * Update DB version. * * @return void */ function kkart_update_343_db_version() { KKART_Install::update_db_version( '3.4.3' ); } /** * Recreate user roles so existing users will get the new capabilities. * * @return void */ function kkart_update_344_recreate_roles() { KKART_Install::remove_roles(); KKART_Install::create_roles(); } /** * Update DB version. * * @return void */ function kkart_update_344_db_version() { KKART_Install::update_db_version( '3.4.4' ); } /** * Set the comment type to 'review' for product reviews that don't have a comment type. */ function kkart_update_350_reviews_comment_type() { global $wpdb; $wpdb->query( "UPDATE {$wpdb->prefix}comments JOIN {$wpdb->prefix}posts ON {$wpdb->prefix}posts.ID = {$wpdb->prefix}comments.comment_post_ID AND ( {$wpdb->prefix}posts.post_type = 'product' OR {$wpdb->prefix}posts.post_type = 'product_variation' ) SET {$wpdb->prefix}comments.comment_type = 'review' WHERE {$wpdb->prefix}comments.comment_type = ''" ); } /** * Update DB Version. */ function kkart_update_350_db_version() { KKART_Install::update_db_version( '3.5.0' ); } /** * Drop the fk_kkart_download_log_permission_id FK as we use a new one with the table and blog prefix for MS compatability. * * @return void */ function kkart_update_352_drop_download_log_fk() { global $wpdb; $results = $wpdb->get_results( "SELECT CONSTRAINT_NAME FROM information_schema.TABLE_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = '{$wpdb->dbname}' AND CONSTRAINT_NAME = 'fk_kkart_download_log_permission_id' AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = '{$wpdb->prefix}kkart_download_log'" ); // We only need to drop the old key as KKART_Install::create_tables() takes care of creating the new FK. if ( $results ) { $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_download_log DROP FOREIGN KEY fk_kkart_download_log_permission_id" ); // phpcs:ignore WordPress.WP.PreparedSQL.NotPrepared } } /** * Remove edit_user capabilities from shop managers and use "translated" capabilities instead. * See kkart_shop_manager_has_capability function. */ function kkart_update_354_modify_shop_manager_caps() { global $wp_roles; if ( ! class_exists( 'WP_Roles' ) ) { return; } if ( ! isset( $wp_roles ) ) { $wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine } $wp_roles->remove_cap( 'shop_manager', 'edit_users' ); } /** * Update DB Version. */ function kkart_update_354_db_version() { KKART_Install::update_db_version( '3.5.4' ); } /** * Update product lookup tables in bulk. */ function kkart_update_360_product_lookup_tables() { kkart_update_product_lookup_tables(); } /** * Renames ordering meta to be consistent across taxonomies. */ function kkart_update_360_term_meta() { global $wpdb; $wpdb->query( "UPDATE {$wpdb->termmeta} SET meta_key = 'order' WHERE meta_key LIKE 'order_pa_%';" ); } /** * Add new user_order_remaining_expires to speed up user download permission fetching. * * @return void */ function kkart_update_360_downloadable_product_permissions_index() { global $wpdb; $index_exists = $wpdb->get_row( "SHOW INDEX FROM {$wpdb->prefix}kkart_downloadable_product_permissions WHERE key_name = 'user_order_remaining_expires'" ); if ( is_null( $index_exists ) ) { $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_downloadable_product_permissions ADD INDEX user_order_remaining_expires (user_id,order_id,downloads_remaining,access_expires)" ); } } /** * Update DB Version. */ function kkart_update_360_db_version() { KKART_Install::update_db_version( '3.6.0' ); } /** * Put tax classes into a DB table. * * @return void */ function kkart_update_370_tax_rate_classes() { global $wpdb; $classes = array_map( 'trim', explode( "\n", get_option( 'kkart_tax_classes' ) ) ); if ( $classes ) { foreach ( $classes as $class ) { if ( empty( $class ) ) { continue; } KKART_Tax::create_tax_class( $class ); } } delete_option( 'kkart_tax_classes' ); } /** * Update currency settings for 3.7.0 * * @return void */ function kkart_update_370_mro_std_currency() { global $wpdb; // Fix currency settings for MRU and STN currency. $current_currency = get_option( 'kkart_currency' ); if ( 'MRO' === $current_currency ) { update_option( 'kkart_currency', 'MRU' ); } if ( 'STD' === $current_currency ) { update_option( 'kkart_currency', 'STN' ); } // Update MRU currency code. $wpdb->update( $wpdb->postmeta, array( 'meta_value' => 'MRU', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ), array( 'meta_key' => '_order_currency', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => 'MRO', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ) ); // Update STN currency code. $wpdb->update( $wpdb->postmeta, array( 'meta_value' => 'STN', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ), array( 'meta_key' => '_order_currency', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key 'meta_value' => 'STD', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value ) ); } /** * Update DB Version. */ function kkart_update_370_db_version() { KKART_Install::update_db_version( '3.7.0' ); } /** * We've moved the MaxMind database to a new location, as per the TOS' requirement that the database not * be publicly accessible. */ function kkart_update_390_move_maxmind_database() { // Make sure to use all of the correct filters to pull the local database path. $old_path = apply_filters( 'kkart_geolocation_local_database_path', WP_CONTENT_DIR . '/uploads/GeoLite2-Country.mmdb', 2 ); // Generate a prefix for the old file and store it in the integration as it would expect it. $prefix = wp_generate_password( 32, false ); update_option( 'kkart_maxmind_geolocation_settings', array( 'database_prefix' => $prefix ) ); // Generate the new path in the same way that the integration will. $uploads_dir = wp_upload_dir(); $new_path = trailingslashit( $uploads_dir['basedir'] ) . 'kkart_uploads/' . $prefix . '-GeoLite2-Country.mmdb'; $new_path = apply_filters( 'kkart_geolocation_local_database_path', $new_path, 2 ); $new_path = apply_filters( 'kkart_maxmind_geolocation_database_path', $new_path ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged @rename( $old_path, $new_path ); } /** * So that we can best meet MaxMind's TOS, the geolocation database update cron should run once per 15 days. */ function kkart_update_390_change_geolocation_database_update_cron() { wp_clear_scheduled_hook( 'kkart_geoip_updater' ); wp_schedule_event( time() + ( DAY_IN_SECONDS * 15 ), 'fifteendays', 'kkart_geoip_updater' ); } /** * Update DB version. */ function kkart_update_390_db_version() { KKART_Install::update_db_version( '3.9.0' ); } /** * Increase column size */ function kkart_update_400_increase_size_of_column() { global $wpdb; $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_product_meta_lookup MODIFY COLUMN `min_price` decimal(19,4) NULL default NULL" ); $wpdb->query( "ALTER TABLE {$wpdb->prefix}kkart_product_meta_lookup MODIFY COLUMN `max_price` decimal(19,4) NULL default NULL" ); } /** * Reset ActionScheduler migration status. Needs AS >= 3.0 shipped with KKART >= 4.0. */ function kkart_update_400_reset_action_scheduler_migration_status() { if ( class_exists( 'ActionScheduler_DataController' ) && method_exists( 'ActionScheduler_DataController', 'mark_migration_incomplete' ) ) { \ActionScheduler_DataController::mark_migration_incomplete(); } } /** * Update DB version. */ function kkart_update_400_db_version() { KKART_Install::update_db_version( '4.0.0' ); } /** * Register attributes as terms for variable products, in increments of 100 products. * * This migration was added to support a new mechanism to improve the filtering of * variable products by attribute (https://github.com/kkart/kkart/pull/26260), * however that mechanism was later reverted (https://github.com/kkart/kkart/pull/27625) * due to numerous issues found. Thus the migration is no longer needed. * * @return bool true if the migration needs to be run again. */ function kkart_update_440_insert_attribute_terms_for_variable_products() { return false; } /** * Update DB version. */ function kkart_update_440_db_version() { KKART_Install::update_db_version( '4.4.0' ); } /** * Update DB version to 4.5.0. */ function kkart_update_450_db_version() { KKART_Install::update_db_version( '4.5.0' ); } /** * Sanitize all coupons code. * * @return bool True to run again, false if completed. */ function kkart_update_450_sanitize_coupons_code() { global $wpdb; $coupon_id = 0; $last_coupon_id = get_option( 'kkart_update_450_last_coupon_id', '0' ); $coupons = $wpdb->get_results( $wpdb->prepare( "SELECT ID, post_title FROM $wpdb->posts WHERE ID > %d AND post_type = 'shop_coupon' LIMIT 10", $last_coupon_id ), ARRAY_A ); if ( empty( $coupons ) ) { delete_option( 'kkart_update_450_last_coupon_id' ); return false; } foreach ( $coupons as $key => $data ) { $coupon_id = intval( $data['ID'] ); $code = trim( wp_filter_kses( $data['post_title'] ) ); if ( ! empty( $code ) && $data['post_title'] !== $code ) { $wpdb->update( $wpdb->posts, array( 'post_title' => $code, ), array( 'ID' => $coupon_id, ), array( '%s', ), array( '%d', ) ); // Clean cache. clean_post_cache( $coupon_id ); wp_cache_delete( KKART_Cache_Helper::get_cache_prefix( 'coupons' ) . 'coupon_id_from_code_' . $data['post_title'], 'coupons' ); } } // Start the run again. if ( $coupon_id ) { return update_option( 'kkart_update_450_last_coupon_id', $coupon_id ); } delete_option( 'kkart_update_450_last_coupon_id' ); return false; } PK!Πb;\4\4class-kkart-shipping-zone.phpnu[ '', 'zone_order' => 0, 'zone_locations' => array(), ); /** * Constructor for zones. * * @param int|object $zone Zone ID to load from the DB or zone object. */ public function __construct( $zone = null ) { if ( is_numeric( $zone ) && ! empty( $zone ) ) { $this->set_id( $zone ); } elseif ( is_object( $zone ) ) { $this->set_id( $zone->zone_id ); } elseif ( 0 === $zone || '0' === $zone ) { $this->set_id( 0 ); } else { $this->set_object_read( true ); } $this->data_store = KKART_Data_Store::load( 'shipping-zone' ); if ( false === $this->get_object_read() ) { $this->data_store->read( $this ); } } /** * -------------------------------------------------------------------------- * Getters * -------------------------------------------------------------------------- */ /** * Get zone name. * * @param string $context View or edit context. * @return string */ public function get_zone_name( $context = 'view' ) { return $this->get_prop( 'zone_name', $context ); } /** * Get zone order. * * @param string $context View or edit context. * @return int */ public function get_zone_order( $context = 'view' ) { return $this->get_prop( 'zone_order', $context ); } /** * Get zone locations. * * @param string $context View or edit context. * @return array of zone objects */ public function get_zone_locations( $context = 'view' ) { return $this->get_prop( 'zone_locations', $context ); } /** * Return a text string representing what this zone is for. * * @param int $max Max locations to return. * @param string $context View or edit context. * @return string */ public function get_formatted_location( $max = 10, $context = 'view' ) { $location_parts = array(); $all_continents = KKART()->countries->get_continents(); $all_countries = KKART()->countries->get_countries(); $all_states = KKART()->countries->get_states(); $locations = $this->get_zone_locations( $context ); $continents = array_filter( $locations, array( $this, 'location_is_continent' ) ); $countries = array_filter( $locations, array( $this, 'location_is_country' ) ); $states = array_filter( $locations, array( $this, 'location_is_state' ) ); $postcodes = array_filter( $locations, array( $this, 'location_is_postcode' ) ); foreach ( $continents as $location ) { $location_parts[] = $all_continents[ $location->code ]['name']; } foreach ( $countries as $location ) { $location_parts[] = $all_countries[ $location->code ]; } foreach ( $states as $location ) { $location_codes = explode( ':', $location->code ); $location_parts[] = $all_states[ $location_codes[0] ][ $location_codes[1] ]; } foreach ( $postcodes as $location ) { $location_parts[] = $location->code; } // Fix display of encoded characters. $location_parts = array_map( 'html_entity_decode', $location_parts ); if ( count( $location_parts ) > $max ) { $remaining = count( $location_parts ) - $max; // @codingStandardsIgnoreStart return sprintf( _n( '%s and %d other region', '%s and %d other regions', $remaining, 'kkart' ), implode( ', ', array_splice( $location_parts, 0, $max ) ), $remaining ); // @codingStandardsIgnoreEnd } elseif ( ! empty( $location_parts ) ) { return implode( ', ', $location_parts ); } else { return __( 'Everywhere', 'kkart' ); } } /** * Get shipping methods linked to this zone. * * @param bool $enabled_only Only return enabled methods. * @param string $context Getting shipping methods for what context. Valid values, admin, json. * @return array of objects */ public function get_shipping_methods( $enabled_only = false, $context = 'admin' ) { if ( null === $this->get_id() ) { return array(); } $raw_methods = $this->data_store->get_methods( $this->get_id(), $enabled_only ); $kkart_shipping = KKART_Shipping::instance(); $allowed_classes = $kkart_shipping->get_shipping_method_class_names(); $methods = array(); foreach ( $raw_methods as $raw_method ) { if ( in_array( $raw_method->method_id, array_keys( $allowed_classes ), true ) ) { $class_name = $allowed_classes[ $raw_method->method_id ]; $instance_id = $raw_method->instance_id; // The returned array may contain instances of shipping methods, as well // as classes. If the "class" is an instance, just use it. If not, // create an instance. if ( is_object( $class_name ) ) { $class_name_of_instance = get_class( $class_name ); $methods[ $instance_id ] = new $class_name_of_instance( $instance_id ); } else { // If the class is not an object, it should be a string. It's better // to double check, to be sure (a class must be a string, anything) // else would be useless. if ( is_string( $class_name ) && class_exists( $class_name ) ) { $methods[ $instance_id ] = new $class_name( $instance_id ); } } // Let's make sure that we have an instance before setting its attributes. if ( is_object( $methods[ $instance_id ] ) ) { $methods[ $instance_id ]->method_order = absint( $raw_method->method_order ); $methods[ $instance_id ]->enabled = $raw_method->is_enabled ? 'yes' : 'no'; $methods[ $instance_id ]->has_settings = $methods[ $instance_id ]->has_settings(); $methods[ $instance_id ]->settings_html = $methods[ $instance_id ]->supports( 'instance-settings-modal' ) ? $methods[ $instance_id ]->get_admin_options_html() : false; $methods[ $instance_id ]->method_description = wp_kses_post( wpautop( $methods[ $instance_id ]->method_description ) ); } if ( 'json' === $context ) { // We don't want the entire object in this context, just the public props. $methods[ $instance_id ] = (object) get_object_vars( $methods[ $instance_id ] ); unset( $methods[ $instance_id ]->instance_form_fields, $methods[ $instance_id ]->form_fields ); } } } uasort( $methods, 'kkart_shipping_zone_method_order_uasort_comparison' ); return apply_filters( 'kkart_shipping_zone_shipping_methods', $methods, $raw_methods, $allowed_classes, $this ); } /** * -------------------------------------------------------------------------- * Setters * -------------------------------------------------------------------------- */ /** * Set zone name. * * @param string $set Value to set. */ public function set_zone_name( $set ) { $this->set_prop( 'zone_name', kkart_clean( $set ) ); } /** * Set zone order. Value to set. * * @param int $set Value to set. */ public function set_zone_order( $set ) { $this->set_prop( 'zone_order', absint( $set ) ); } /** * Set zone locations. * * @since 3.0.0 * @param array $locations Value to set. */ public function set_zone_locations( $locations ) { if ( 0 !== $this->get_id() ) { $this->set_prop( 'zone_locations', $locations ); } } /** * -------------------------------------------------------------------------- * Other * -------------------------------------------------------------------------- */ /** * Save zone data to the database. * * @return int */ public function save() { if ( ! $this->get_zone_name() ) { $this->set_zone_name( $this->generate_zone_name() ); } if ( ! $this->data_store ) { return $this->get_id(); } /** * Trigger action before saving to the DB. Allows you to adjust object props before save. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_before_' . $this->object_type . '_object_save', $this, $this->data_store ); if ( null !== $this->get_id() ) { $this->data_store->update( $this ); } else { $this->data_store->create( $this ); } /** * Trigger action after saving to the DB. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_after_' . $this->object_type . '_object_save', $this, $this->data_store ); return $this->get_id(); } /** * Generate a zone name based on location. * * @return string */ protected function generate_zone_name() { $zone_name = $this->get_formatted_location(); if ( empty( $zone_name ) ) { $zone_name = __( 'Zone', 'kkart' ); } return $zone_name; } /** * Location type detection. * * @param object $location Location to check. * @return boolean */ private function location_is_continent( $location ) { return 'continent' === $location->type; } /** * Location type detection. * * @param object $location Location to check. * @return boolean */ private function location_is_country( $location ) { return 'country' === $location->type; } /** * Location type detection. * * @param object $location Location to check. * @return boolean */ private function location_is_state( $location ) { return 'state' === $location->type; } /** * Location type detection. * * @param object $location Location to check. * @return boolean */ private function location_is_postcode( $location ) { return 'postcode' === $location->type; } /** * Is passed location type valid? * * @param string $type Type to check. * @return boolean */ public function is_valid_location_type( $type ) { return in_array( $type, apply_filters( 'kkart_valid_location_types', array( 'postcode', 'state', 'country', 'continent' ) ), true ); } /** * Add location (state or postcode) to a zone. * * @param string $code Location code. * @param string $type state or postcode. */ public function add_location( $code, $type ) { if ( 0 !== $this->get_id() && $this->is_valid_location_type( $type ) ) { if ( 'postcode' === $type ) { $code = trim( strtoupper( str_replace( chr( 226 ) . chr( 128 ) . chr( 166 ), '...', $code ) ) ); // No normalization - postcodes are matched against both normal and formatted versions to support wildcards. } $location = array( 'code' => kkart_clean( $code ), 'type' => kkart_clean( $type ), ); $zone_locations = $this->get_prop( 'zone_locations', 'edit' ); $zone_locations[] = (object) $location; $this->set_prop( 'zone_locations', $zone_locations ); } } /** * Clear all locations for this zone. * * @param array|string $types of location to clear. */ public function clear_locations( $types = array( 'postcode', 'state', 'country', 'continent' ) ) { if ( ! is_array( $types ) ) { $types = array( $types ); } $zone_locations = $this->get_prop( 'zone_locations', 'edit' ); foreach ( $zone_locations as $key => $values ) { if ( in_array( $values->type, $types, true ) ) { unset( $zone_locations[ $key ] ); } } $zone_locations = array_values( $zone_locations ); // reindex. $this->set_prop( 'zone_locations', $zone_locations ); } /** * Set locations. * * @param array $locations Array of locations. */ public function set_locations( $locations = array() ) { $this->clear_locations(); foreach ( $locations as $location ) { $this->add_location( $location['code'], $location['type'] ); } } /** * Add a shipping method to this zone. * * @param string $type shipping method type. * @return int new instance_id, 0 on failure */ public function add_shipping_method( $type ) { if ( null === $this->get_id() ) { $this->save(); } $instance_id = 0; $kkart_shipping = KKART_Shipping::instance(); $allowed_classes = $kkart_shipping->get_shipping_method_class_names(); $count = $this->data_store->get_method_count( $this->get_id() ); if ( in_array( $type, array_keys( $allowed_classes ), true ) ) { $instance_id = $this->data_store->add_method( $this->get_id(), $type, $count + 1 ); } if ( $instance_id ) { do_action( 'kkart_shipping_zone_method_added', $instance_id, $type, $this->get_id() ); } KKART_Cache_Helper::get_transient_version( 'shipping', true ); return $instance_id; } /** * Delete a shipping method from a zone. * * @param int $instance_id Shipping method instance ID. * @return True on success, false on failure */ public function delete_shipping_method( $instance_id ) { if ( null === $this->get_id() ) { return false; } // Get method details. $method = $this->data_store->get_method( $instance_id ); if ( $method ) { $this->data_store->delete_method( $instance_id ); do_action( 'kkart_shipping_zone_method_deleted', $instance_id, $method->method_id, $this->get_id() ); } KKART_Cache_Helper::get_transient_version( 'shipping', true ); return true; } } PK!52 2 $abstracts/abstract-kkart-session.phpnu[get( $key ); } /** * Magic set method. * * @param mixed $key Key to set. * @param mixed $value Value to set. */ public function __set( $key, $value ) { $this->set( $key, $value ); } /** * Magic isset method. * * @param mixed $key Key to check. * @return bool */ public function __isset( $key ) { return isset( $this->_data[ sanitize_title( $key ) ] ); } /** * Magic unset method. * * @param mixed $key Key to unset. */ public function __unset( $key ) { if ( isset( $this->_data[ $key ] ) ) { unset( $this->_data[ $key ] ); $this->_dirty = true; } } /** * Get a session variable. * * @param string $key Key to get. * @param mixed $default used if the session variable isn't set. * @return array|string value of session variable */ public function get( $key, $default = null ) { $key = sanitize_key( $key ); return isset( $this->_data[ $key ] ) ? maybe_unserialize( $this->_data[ $key ] ) : $default; } /** * Set a session variable. * * @param string $key Key to set. * @param mixed $value Value to set. */ public function set( $key, $value ) { if ( $value !== $this->get( $key ) ) { $this->_data[ sanitize_key( $key ) ] = maybe_serialize( $value ); $this->_dirty = true; } } /** * Get customer ID. * * @return int */ public function get_customer_id() { return $this->_customer_id; } } PK!℀/"abstracts/abstract-kkart-order.phpnu[ 0, 'status' => '', 'currency' => '', 'version' => '', 'prices_include_tax' => false, 'date_created' => null, 'date_modified' => null, 'discount_total' => 0, 'discount_tax' => 0, 'shipping_total' => 0, 'shipping_tax' => 0, 'cart_tax' => 0, 'total' => 0, 'total_tax' => 0, ); /** * Order items will be stored here, sometimes before they persist in the DB. * * @since 3.0.0 * @var array */ protected $items = array(); /** * Order items that need deleting are stored here. * * @since 3.0.0 * @var array */ protected $items_to_delete = array(); /** * Stores meta in cache for future reads. * * A group must be set to to enable caching. * * @var string */ protected $cache_group = 'orders'; /** * Which data store to load. * * @var string */ protected $data_store_name = 'order'; /** * This is the name of this object type. * * @var string */ protected $object_type = 'order'; /** * Get the order if ID is passed, otherwise the order is new and empty. * This class should NOT be instantiated, but the kkart_get_order function or new KKART_Order_Factory * should be used. It is possible, but the aforementioned are preferred and are the only * methods that will be maintained going forward. * * @param int|object|KKART_Order $order Order to read. */ public function __construct( $order = 0 ) { parent::__construct( $order ); if ( is_numeric( $order ) && $order > 0 ) { $this->set_id( $order ); } elseif ( $order instanceof self ) { $this->set_id( $order->get_id() ); } elseif ( ! empty( $order->ID ) ) { $this->set_id( $order->ID ); } else { $this->set_object_read( true ); } $this->data_store = KKART_Data_Store::load( $this->data_store_name ); if ( $this->get_id() > 0 ) { $this->data_store->read( $this ); } } /** * Get internal type. * * @return string */ public function get_type() { return 'shop_order'; } /** * Get all class data in array format. * * @since 3.0.0 * @return array */ public function get_data() { return array_merge( array( 'id' => $this->get_id(), ), $this->data, array( 'meta_data' => $this->get_meta_data(), 'line_items' => $this->get_items( 'line_item' ), 'tax_lines' => $this->get_items( 'tax' ), 'shipping_lines' => $this->get_items( 'shipping' ), 'fee_lines' => $this->get_items( 'fee' ), 'coupon_lines' => $this->get_items( 'coupon' ), ) ); } /* |-------------------------------------------------------------------------- | CRUD methods |-------------------------------------------------------------------------- | | Methods which create, read, update and delete orders from the database. | Written in abstract fashion so that the way orders are stored can be | changed more easily in the future. | | A save method is included for convenience (chooses update or create based | on if the order exists yet). | */ /** * Save data to the database. * * @since 3.0.0 * @return int order ID */ public function save() { if ( ! $this->data_store ) { return $this->get_id(); } try { /** * Trigger action before saving to the DB. Allows you to adjust object props before save. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_before_' . $this->object_type . '_object_save', $this, $this->data_store ); if ( $this->get_id() ) { $this->data_store->update( $this ); } else { $this->data_store->create( $this ); } $this->save_items(); /** * Trigger action after saving to the DB. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_after_' . $this->object_type . '_object_save', $this, $this->data_store ); } catch ( Exception $e ) { $this->handle_exception( $e, __( 'Error saving order.', 'kkart' ) ); } return $this->get_id(); } /** * Log an error about this order is exception is encountered. * * @param Exception $e Exception object. * @param string $message Message regarding exception thrown. * @since 3.7.0 */ protected function handle_exception( $e, $message = 'Error' ) { kkart_get_logger()->error( $message, array( 'order' => $this, 'error' => $e, ) ); } /** * Save all order items which are part of this order. */ protected function save_items() { $items_changed = false; foreach ( $this->items_to_delete as $item ) { $item->delete(); $items_changed = true; } $this->items_to_delete = array(); // Add/save items. foreach ( $this->items as $item_group => $items ) { if ( is_array( $items ) ) { $items = array_filter( $items ); foreach ( $items as $item_key => $item ) { $item->set_order_id( $this->get_id() ); $item_id = $item->save(); // If ID changed (new item saved to DB)... if ( $item_id !== $item_key ) { $this->items[ $item_group ][ $item_id ] = $item; unset( $this->items[ $item_group ][ $item_key ] ); $items_changed = true; } } } } if ( $items_changed ) { delete_transient( 'kkart_order_' . $this->get_id() . '_needs_processing' ); } } /* |-------------------------------------------------------------------------- | Getters |-------------------------------------------------------------------------- */ /** * Get parent order ID. * * @since 3.0.0 * @param string $context View or edit context. * @return integer */ public function get_parent_id( $context = 'view' ) { return $this->get_prop( 'parent_id', $context ); } /** * Gets order currency. * * @param string $context View or edit context. * @return string */ public function get_currency( $context = 'view' ) { return $this->get_prop( 'currency', $context ); } /** * Get order_version. * * @param string $context View or edit context. * @return string */ public function get_version( $context = 'view' ) { return $this->get_prop( 'version', $context ); } /** * Get prices_include_tax. * * @param string $context View or edit context. * @return bool */ public function get_prices_include_tax( $context = 'view' ) { return $this->get_prop( 'prices_include_tax', $context ); } /** * Get date_created. * * @param string $context View or edit context. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_created( $context = 'view' ) { return $this->get_prop( 'date_created', $context ); } /** * Get date_modified. * * @param string $context View or edit context. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_modified( $context = 'view' ) { return $this->get_prop( 'date_modified', $context ); } /** * Return the order statuses without kkart- internal prefix. * * @param string $context View or edit context. * @return string */ public function get_status( $context = 'view' ) { $status = $this->get_prop( 'status', $context ); if ( empty( $status ) && 'view' === $context ) { // In view context, return the default status if no status has been set. $status = apply_filters( 'kkart_default_order_status', 'pending' ); } return $status; } /** * Get discount_total. * * @param string $context View or edit context. * @return string */ public function get_discount_total( $context = 'view' ) { return $this->get_prop( 'discount_total', $context ); } /** * Get discount_tax. * * @param string $context View or edit context. * @return string */ public function get_discount_tax( $context = 'view' ) { return $this->get_prop( 'discount_tax', $context ); } /** * Get shipping_total. * * @param string $context View or edit context. * @return string */ public function get_shipping_total( $context = 'view' ) { return $this->get_prop( 'shipping_total', $context ); } /** * Get shipping_tax. * * @param string $context View or edit context. * @return string */ public function get_shipping_tax( $context = 'view' ) { return $this->get_prop( 'shipping_tax', $context ); } /** * Gets cart tax amount. * * @param string $context View or edit context. * @return float */ public function get_cart_tax( $context = 'view' ) { return $this->get_prop( 'cart_tax', $context ); } /** * Gets order grand total. incl. taxes. Used in gateways. * * @param string $context View or edit context. * @return float */ public function get_total( $context = 'view' ) { return $this->get_prop( 'total', $context ); } /** * Get total tax amount. Alias for get_order_tax(). * * @param string $context View or edit context. * @return float */ public function get_total_tax( $context = 'view' ) { return $this->get_prop( 'total_tax', $context ); } /* |-------------------------------------------------------------------------- | Non-CRUD Getters |-------------------------------------------------------------------------- */ /** * Gets the total discount amount. * * @param bool $ex_tax Show discount excl any tax. * @return float */ public function get_total_discount( $ex_tax = true ) { if ( $ex_tax ) { $total_discount = $this->get_discount_total(); } else { $total_discount = $this->get_discount_total() + $this->get_discount_tax(); } return apply_filters( 'kkart_order_get_total_discount', NumberUtil::round( $total_discount, KKART_ROUNDING_PRECISION ), $this ); } /** * Gets order subtotal. * * @return float */ public function get_subtotal() { $subtotal = NumberUtil::round( $this->get_cart_subtotal_for_order(), kkart_get_price_decimals() ); return apply_filters( 'kkart_order_get_subtotal', (float) $subtotal, $this ); } /** * Get taxes, merged by code, formatted ready for output. * * @return array */ public function get_tax_totals() { $tax_totals = array(); foreach ( $this->get_items( 'tax' ) as $key => $tax ) { $code = $tax->get_rate_code(); if ( ! isset( $tax_totals[ $code ] ) ) { $tax_totals[ $code ] = new stdClass(); $tax_totals[ $code ]->amount = 0; } $tax_totals[ $code ]->id = $key; $tax_totals[ $code ]->rate_id = $tax->get_rate_id(); $tax_totals[ $code ]->is_compound = $tax->is_compound(); $tax_totals[ $code ]->label = $tax->get_label(); $tax_totals[ $code ]->amount += (float) $tax->get_tax_total() + (float) $tax->get_shipping_tax_total(); $tax_totals[ $code ]->formatted_amount = kkart_price( $tax_totals[ $code ]->amount, array( 'currency' => $this->get_currency() ) ); } if ( apply_filters( 'kkart_order_hide_zero_taxes', true ) ) { $amounts = array_filter( wp_list_pluck( $tax_totals, 'amount' ) ); $tax_totals = array_intersect_key( $tax_totals, $amounts ); } return apply_filters( 'kkart_order_get_tax_totals', $tax_totals, $this ); } /** * Get all valid statuses for this order * * @since 3.0.0 * @return array Internal status keys e.g. 'kkart-processing' */ protected function get_valid_statuses() { return array_keys( kkart_get_order_statuses() ); } /** * Get user ID. Used by orders, not other order types like refunds. * * @param string $context View or edit context. * @return int */ public function get_user_id( $context = 'view' ) { return 0; } /** * Get user. Used by orders, not other order types like refunds. * * @return WP_User|false */ public function get_user() { return false; } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- | | Functions for setting order data. These should not update anything in the | database itself and should only change what is stored in the class | object. However, for backwards compatibility pre 3.0.0 some of these | setters may handle both. */ /** * Set parent order ID. * * @since 3.0.0 * @param int $value Value to set. * @throws KKART_Data_Exception Exception thrown if parent ID does not exist or is invalid. */ public function set_parent_id( $value ) { if ( $value && ( $value === $this->get_id() || ! kkart_get_order( $value ) ) ) { $this->error( 'order_invalid_parent_id', __( 'Invalid parent ID', 'kkart' ) ); } $this->set_prop( 'parent_id', absint( $value ) ); } /** * Set order status. * * @since 3.0.0 * @param string $new_status Status to change the order to. No internal kkart- prefix is required. * @return array details of change */ public function set_status( $new_status ) { $old_status = $this->get_status(); $new_status = 'kkart-' === substr( $new_status, 0, 6 ) ? substr( $new_status, 6 ) : $new_status; // If setting the status, ensure it's set to a valid status. if ( true === $this->object_read ) { // Only allow valid new status. if ( ! in_array( 'kkart-' . $new_status, $this->get_valid_statuses(), true ) && 'trash' !== $new_status ) { $new_status = 'pending'; } // If the old status is set but unknown (e.g. draft) assume its pending for action usage. if ( $old_status && ! in_array( 'kkart-' . $old_status, $this->get_valid_statuses(), true ) && 'trash' !== $old_status ) { $old_status = 'pending'; } } $this->set_prop( 'status', $new_status ); return array( 'from' => $old_status, 'to' => $new_status, ); } /** * Set order_version. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_version( $value ) { $this->set_prop( 'version', $value ); } /** * Set order_currency. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_currency( $value ) { if ( $value && ! in_array( $value, array_keys( get_kkart_currencies() ), true ) ) { $this->error( 'order_invalid_currency', __( 'Invalid currency code', 'kkart' ) ); } $this->set_prop( 'currency', $value ? $value : get_kkart_currency() ); } /** * Set prices_include_tax. * * @param bool $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_prices_include_tax( $value ) { $this->set_prop( 'prices_include_tax', (bool) $value ); } /** * Set date_created. * * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if there is no date. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_date_created( $date = null ) { $this->set_date_prop( 'date_created', $date ); } /** * Set date_modified. * * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if there is no date. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_date_modified( $date = null ) { $this->set_date_prop( 'date_modified', $date ); } /** * Set discount_total. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_discount_total( $value ) { $this->set_prop( 'discount_total', kkart_format_decimal( $value ) ); } /** * Set discount_tax. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_discount_tax( $value ) { $this->set_prop( 'discount_tax', kkart_format_decimal( $value ) ); } /** * Set shipping_total. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_shipping_total( $value ) { $this->set_prop( 'shipping_total', kkart_format_decimal( $value ) ); } /** * Set shipping_tax. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_shipping_tax( $value ) { $this->set_prop( 'shipping_tax', kkart_format_decimal( $value ) ); $this->set_total_tax( (float) $this->get_cart_tax() + (float) $this->get_shipping_tax() ); } /** * Set cart tax. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_cart_tax( $value ) { $this->set_prop( 'cart_tax', kkart_format_decimal( $value ) ); $this->set_total_tax( (float) $this->get_cart_tax() + (float) $this->get_shipping_tax() ); } /** * Sets order tax (sum of cart and shipping tax). Used internally only. * * @param string $value Value to set. * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ protected function set_total_tax( $value ) { // We round here because this is a total entry, as opposed to line items in other setters. $this->set_prop( 'total_tax', kkart_format_decimal( NumberUtil::round( $value, kkart_get_price_decimals() ) ) ); } /** * Set total. * * @param string $value Value to set. * @param string $deprecated Function used to set different totals based on this. * * @return bool|void * @throws KKART_Data_Exception Exception may be thrown if value is invalid. */ public function set_total( $value, $deprecated = '' ) { if ( $deprecated ) { kkart_deprecated_argument( 'total_type', '3.0', 'Use dedicated total setter methods instead.' ); return $this->legacy_set_total( $value, $deprecated ); } $this->set_prop( 'total', kkart_format_decimal( $value, kkart_get_price_decimals() ) ); } /* |-------------------------------------------------------------------------- | Order Item Handling |-------------------------------------------------------------------------- | | Order items are used for products, taxes, shipping, and fees within | each order. */ /** * Remove all line items (products, coupons, shipping, taxes) from the order. * * @param string $type Order item type. Default null. */ public function remove_order_items( $type = null ) { if ( ! empty( $type ) ) { $this->data_store->delete_items( $this, $type ); $group = $this->type_to_group( $type ); if ( $group ) { unset( $this->items[ $group ] ); } } else { $this->data_store->delete_items( $this ); $this->items = array(); } } /** * Convert a type to a types group. * * @param string $type type to lookup. * @return string */ protected function type_to_group( $type ) { $type_to_group = apply_filters( 'kkart_order_type_to_group', array( 'line_item' => 'line_items', 'tax' => 'tax_lines', 'shipping' => 'shipping_lines', 'fee' => 'fee_lines', 'coupon' => 'coupon_lines', ) ); return isset( $type_to_group[ $type ] ) ? $type_to_group[ $type ] : ''; } /** * Return an array of items/products within this order. * * @param string|array $types Types of line items to get (array or string). * @return KKART_Order_Item[] */ public function get_items( $types = 'line_item' ) { $items = array(); $types = array_filter( (array) $types ); foreach ( $types as $type ) { $group = $this->type_to_group( $type ); if ( $group ) { if ( ! isset( $this->items[ $group ] ) ) { $this->items[ $group ] = array_filter( $this->data_store->read_items( $this, $type ) ); } // Don't use array_merge here because keys are numeric. $items = $items + $this->items[ $group ]; } } return apply_filters( 'kkart_order_get_items', $items, $this, $types ); } /** * Return array of values for calculations. * * @param string $field Field name to return. * * @return array Array of values. */ protected function get_values_for_total( $field ) { $items = array_map( function ( $item ) use ( $field ) { return kkart_add_number_precision( $item[ $field ], false ); }, array_values( $this->get_items() ) ); return $items; } /** * Return an array of coupons within this order. * * @since 3.7.0 * @return KKART_Order_Item_Coupon[] */ public function get_coupons() { return $this->get_items( 'coupon' ); } /** * Return an array of fees within this order. * * @return KKART_Order_item_Fee[] */ public function get_fees() { return $this->get_items( 'fee' ); } /** * Return an array of taxes within this order. * * @return KKART_Order_Item_Tax[] */ public function get_taxes() { return $this->get_items( 'tax' ); } /** * Return an array of shipping costs within this order. * * @return KKART_Order_Item_Shipping[] */ public function get_shipping_methods() { return $this->get_items( 'shipping' ); } /** * Gets formatted shipping method title. * * @return string */ public function get_shipping_method() { $names = array(); foreach ( $this->get_shipping_methods() as $shipping_method ) { $names[] = $shipping_method->get_name(); } return apply_filters( 'kkart_order_shipping_method', implode( ', ', $names ), $this ); } /** * Get used coupon codes only. * * @since 3.7.0 * @return array */ public function get_coupon_codes() { $coupon_codes = array(); $coupons = $this->get_items( 'coupon' ); if ( $coupons ) { foreach ( $coupons as $coupon ) { $coupon_codes[] = $coupon->get_code(); } } return $coupon_codes; } /** * Gets the count of order items of a certain type. * * @param string $item_type Item type to lookup. * @return int|string */ public function get_item_count( $item_type = '' ) { $items = $this->get_items( empty( $item_type ) ? 'line_item' : $item_type ); $count = 0; foreach ( $items as $item ) { $count += $item->get_quantity(); } return apply_filters( 'kkart_get_item_count', $count, $item_type, $this ); } /** * Get an order item object, based on its type. * * @since 3.0.0 * @param int $item_id ID of item to get. * @param bool $load_from_db Prior to 3.2 this item was loaded direct from KKART_Order_Factory, not this object. This param is here for backwards compatility with that. If false, uses the local items variable instead. * @return KKART_Order_Item|false */ public function get_item( $item_id, $load_from_db = true ) { if ( $load_from_db ) { return KKART_Order_Factory::get_order_item( $item_id ); } // Search for item id. if ( $this->items ) { foreach ( $this->items as $group => $items ) { if ( isset( $items[ $item_id ] ) ) { return $items[ $item_id ]; } } } // Load all items of type and cache. $type = $this->data_store->get_order_item_type( $this, $item_id ); if ( ! $type ) { return false; } $items = $this->get_items( $type ); return ! empty( $items[ $item_id ] ) ? $items[ $item_id ] : false; } /** * Get key for where a certain item type is stored in _items. * * @since 3.0.0 * @param string $item object Order item (product, shipping, fee, coupon, tax). * @return string */ protected function get_items_key( $item ) { if ( is_a( $item, 'KKART_Order_Item_Product' ) ) { return 'line_items'; } elseif ( is_a( $item, 'KKART_Order_Item_Fee' ) ) { return 'fee_lines'; } elseif ( is_a( $item, 'KKART_Order_Item_Shipping' ) ) { return 'shipping_lines'; } elseif ( is_a( $item, 'KKART_Order_Item_Tax' ) ) { return 'tax_lines'; } elseif ( is_a( $item, 'KKART_Order_Item_Coupon' ) ) { return 'coupon_lines'; } return apply_filters( 'kkart_get_items_key', '', $item ); } /** * Remove item from the order. * * @param int $item_id Item ID to delete. * @return false|void */ public function remove_item( $item_id ) { $item = $this->get_item( $item_id, false ); $items_key = $item ? $this->get_items_key( $item ) : false; if ( ! $items_key ) { return false; } // Unset and remove later. $this->items_to_delete[] = $item; unset( $this->items[ $items_key ][ $item->get_id() ] ); } /** * Adds an order item to this order. The order item will not persist until save. * * @since 3.0.0 * @param KKART_Order_Item $item Order item object (product, shipping, fee, coupon, tax). * @return false|void */ public function add_item( $item ) { $items_key = $this->get_items_key( $item ); if ( ! $items_key ) { return false; } // Make sure existing items are loaded so we can append this new one. if ( ! isset( $this->items[ $items_key ] ) ) { $this->items[ $items_key ] = $this->get_items( $item->get_type() ); } // Set parent. $item->set_order_id( $this->get_id() ); // Append new row with generated temporary ID. $item_id = $item->get_id(); if ( $item_id ) { $this->items[ $items_key ][ $item_id ] = $item; } else { $this->items[ $items_key ][ 'new:' . $items_key . count( $this->items[ $items_key ] ) ] = $item; } } /** * Check and records coupon usage tentatively so that counts validation is correct. Display an error if coupon usage limit has been reached. * * If you are using this method, make sure to `release_held_coupons` in case an Exception is thrown. * * @throws Exception When not able to apply coupon. * * @param string $billing_email Billing email of order. */ public function hold_applied_coupons( $billing_email ) { $held_keys = array(); $held_keys_for_user = array(); $error = null; try { foreach ( KKART()->cart->get_applied_coupons() as $code ) { $coupon = new KKART_Coupon( $code ); if ( ! $coupon->get_data_store() ) { continue; } // Hold coupon for when global coupon usage limit is present. if ( 0 < $coupon->get_usage_limit() ) { $held_key = $this->hold_coupon( $coupon ); if ( $held_key ) { $held_keys[ $coupon->get_id() ] = $held_key; } } // Hold coupon for when usage limit per customer is enabled. if ( 0 < $coupon->get_usage_limit_per_user() ) { if ( ! isset( $user_ids_and_emails ) ) { $user_alias = get_current_user_id() ? wp_get_current_user()->ID : sanitize_email( $billing_email ); $user_ids_and_emails = $this->get_billing_and_current_user_aliases( $billing_email ); } $held_key_for_user = $this->hold_coupon_for_users( $coupon, $user_ids_and_emails, $user_alias ); if ( $held_key_for_user ) { $held_keys_for_user[ $coupon->get_id() ] = $held_key_for_user; } } } } catch ( Exception $e ) { $error = $e; } finally { // Even in case of error, we will save keys for whatever coupons that were held so our data remains accurate. // We save them in bulk instead of one by one for performance reasons. if ( 0 < count( $held_keys_for_user ) || 0 < count( $held_keys ) ) { $this->get_data_store()->set_coupon_held_keys( $this, $held_keys, $held_keys_for_user ); } if ( $error instanceof Exception ) { throw $error; } } } /** * Hold coupon if a global usage limit is defined. * * @param KKART_Coupon $coupon Coupon object. * * @return string Meta key which indicates held coupon. * @throws Exception When can't be held. */ private function hold_coupon( $coupon ) { $result = $coupon->get_data_store()->check_and_hold_coupon( $coupon ); if ( false === $result ) { // translators: Actual coupon code. throw new Exception( sprintf( __( 'An unexpected error happened while applying the Coupon %s.', 'kkart' ), esc_html( $coupon->get_code() ) ) ); } elseif ( 0 === $result ) { // translators: Actual coupon code. throw new Exception( sprintf( __( 'Coupon %s was used in another transaction during this checkout, and coupon usage limit is reached. Please remove the coupon and try again.', 'kkart' ), esc_html( $coupon->get_code() ) ) ); } return $result; } /** * Hold coupon if usage limit per customer is defined. * * @param KKART_Coupon $coupon Coupon object. * @param array $user_ids_and_emails Array of user Id and emails to check for usage limit. * @param string $user_alias User ID or email to use to record current usage. * * @return string Meta key which indicates held coupon. * @throws Exception When coupon can't be held. */ private function hold_coupon_for_users( $coupon, $user_ids_and_emails, $user_alias ) { $result = $coupon->get_data_store()->check_and_hold_coupon_for_user( $coupon, $user_ids_and_emails, $user_alias ); if ( false === $result ) { // translators: Actual coupon code. throw new Exception( sprintf( __( 'An unexpected error happened while applying the Coupon %s.', 'kkart' ), esc_html( $coupon->get_code() ) ) ); } elseif ( 0 === $result ) { // translators: Actual coupon code. throw new Exception( sprintf( __( 'You have used this coupon %s in another transaction during this checkout, and coupon usage limit is reached. Please remove the coupon and try again.', 'kkart' ), esc_html( $coupon->get_code() ) ) ); } return $result; } /** * Helper method to get all aliases for current user and provide billing email. * * @param string $billing_email Billing email provided in form. * * @return array Array of all aliases. * @throws Exception When validation fails. */ private function get_billing_and_current_user_aliases( $billing_email ) { $emails = array( $billing_email ); if ( get_current_user_id() ) { $emails[] = wp_get_current_user()->user_email; } $emails = array_unique( array_map( 'strtolower', array_map( 'sanitize_email', $emails ) ) ); $customer_data_store = KKART_Data_Store::load( 'customer' ); $user_ids = $customer_data_store->get_user_ids_for_billing_email( $emails ); return array_merge( $user_ids, $emails ); } /** * Apply a coupon to the order and recalculate totals. * * @since 3.2.0 * @param string|KKART_Coupon $raw_coupon Coupon code or object. * @return true|WP_Error True if applied, error if not. */ public function apply_coupon( $raw_coupon ) { if ( is_a( $raw_coupon, 'KKART_Coupon' ) ) { $coupon = $raw_coupon; } elseif ( is_string( $raw_coupon ) ) { $code = kkart_format_coupon_code( $raw_coupon ); $coupon = new KKART_Coupon( $code ); if ( $coupon->get_code() !== $code ) { return new WP_Error( 'invalid_coupon', __( 'Invalid coupon code', 'kkart' ) ); } } else { return new WP_Error( 'invalid_coupon', __( 'Invalid coupon', 'kkart' ) ); } // Check to make sure coupon is not already applied. $applied_coupons = $this->get_items( 'coupon' ); foreach ( $applied_coupons as $applied_coupon ) { if ( $applied_coupon->get_code() === $coupon->get_code() ) { return new WP_Error( 'invalid_coupon', __( 'Coupon code already applied!', 'kkart' ) ); } } $discounts = new KKART_Discounts( $this ); $applied = $discounts->apply_coupon( $coupon ); if ( is_wp_error( $applied ) ) { return $applied; } $data_store = $coupon->get_data_store(); // Check specific for guest checkouts here as well since KKART_Cart handles that seperately in check_customer_coupons. if ( $data_store && 0 === $this->get_customer_id() ) { $usage_count = $data_store->get_usage_by_email( $coupon, $this->get_billing_email() ); if ( 0 < $coupon->get_usage_limit_per_user() && $usage_count >= $coupon->get_usage_limit_per_user() ) { return new WP_Error( 'invalid_coupon', $coupon->get_coupon_error( 106 ), array( 'status' => 400, ) ); } } $this->set_coupon_discount_amounts( $discounts ); $this->save(); // Recalculate totals and taxes. $this->recalculate_coupons(); // Record usage so counts and validation is correct. $used_by = $this->get_user_id(); if ( ! $used_by ) { $used_by = $this->get_billing_email(); } $coupon->increase_usage_count( $used_by ); return true; } /** * Remove a coupon from the order and recalculate totals. * * Coupons affect line item totals, but there is no relationship between * coupon and line total, so to remove a coupon we need to work from the * line subtotal (price before discount) and re-apply all coupons in this * order. * * Manual discounts are not affected; those are separate and do not affect * stored line totals. * * @since 3.2.0 * @param string $code Coupon code. * @return void */ public function remove_coupon( $code ) { $coupons = $this->get_items( 'coupon' ); // Remove the coupon line. foreach ( $coupons as $item_id => $coupon ) { if ( $coupon->get_code() === $code ) { $this->remove_item( $item_id ); $coupon_object = new KKART_Coupon( $code ); $coupon_object->decrease_usage_count( $this->get_user_id() ); $this->recalculate_coupons(); break; } } } /** * Apply all coupons in this order again to all line items. * This method is public since Kkart 3.8.0. * * @since 3.2.0 */ public function recalculate_coupons() { // Reset line item totals. foreach ( $this->get_items() as $item ) { $item->set_total( $item->get_subtotal() ); $item->set_total_tax( $item->get_subtotal_tax() ); } $discounts = new KKART_Discounts( $this ); foreach ( $this->get_items( 'coupon' ) as $coupon_item ) { $coupon_code = $coupon_item->get_code(); $coupon_id = kkart_get_coupon_id_by_code( $coupon_code ); // If we have a coupon ID (loaded via kkart_get_coupon_id_by_code) we can simply load the new coupon object using the ID. if ( $coupon_id ) { $coupon_object = new KKART_Coupon( $coupon_id ); } else { // If we do not have a coupon ID (was it virtual? has it been deleted?) we must create a temporary coupon using what data we have stored during checkout. $coupon_object = new KKART_Coupon(); $coupon_object->set_props( (array) $coupon_item->get_meta( 'coupon_data', true ) ); $coupon_object->set_code( $coupon_code ); $coupon_object->set_virtual( true ); // If there is no coupon amount (maybe dynamic?), set it to the given **discount** amount so the coupon's same value is applied. if ( ! $coupon_object->get_amount() ) { // If the order originally had prices including tax, remove the discount + discount tax. if ( $this->get_prices_include_tax() ) { $coupon_object->set_amount( $coupon_item->get_discount() + $coupon_item->get_discount_tax() ); } else { $coupon_object->set_amount( $coupon_item->get_discount() ); } $coupon_object->set_discount_type( 'fixed_cart' ); } } /** * Allow developers to filter this coupon before it get's re-applied to the order. * * @since 3.2.0 */ $coupon_object = apply_filters( 'kkart_order_recalculate_coupons_coupon_object', $coupon_object, $coupon_code, $coupon_item, $this ); if ( $coupon_object ) { $discounts->apply_coupon( $coupon_object, false ); } } $this->set_coupon_discount_amounts( $discounts ); $this->set_item_discount_amounts( $discounts ); // Recalculate totals and taxes. $this->calculate_totals( true ); } /** * After applying coupons via the KKART_Discounts class, update line items. * * @since 3.2.0 * @param KKART_Discounts $discounts Discounts class. */ protected function set_item_discount_amounts( $discounts ) { $item_discounts = $discounts->get_discounts_by_item(); if ( $item_discounts ) { foreach ( $item_discounts as $item_id => $amount ) { $item = $this->get_item( $item_id, false ); // If the prices include tax, discounts should be taken off the tax inclusive prices like in the cart. if ( $this->get_prices_include_tax() && kkart_tax_enabled() && 'taxable' === $item->get_tax_status() ) { $taxes = KKART_Tax::calc_tax( $amount, KKART_Tax::get_rates( $item->get_tax_class() ), true ); // Use unrounded taxes so totals will be re-calculated accurately, like in cart. $amount = $amount - array_sum( $taxes ); } $item->set_total( max( 0, $item->get_total() - $amount ) ); } } } /** * After applying coupons via the KKART_Discounts class, update or create coupon items. * * @since 3.2.0 * @param KKART_Discounts $discounts Discounts class. */ protected function set_coupon_discount_amounts( $discounts ) { $coupons = $this->get_items( 'coupon' ); $coupon_code_to_id = kkart_list_pluck( $coupons, 'get_id', 'get_code' ); $all_discounts = $discounts->get_discounts(); $coupon_discounts = $discounts->get_discounts_by_coupon(); if ( $coupon_discounts ) { foreach ( $coupon_discounts as $coupon_code => $amount ) { $item_id = isset( $coupon_code_to_id[ $coupon_code ] ) ? $coupon_code_to_id[ $coupon_code ] : 0; if ( ! $item_id ) { $coupon_item = new KKART_Order_Item_Coupon(); $coupon_item->set_code( $coupon_code ); } else { $coupon_item = $this->get_item( $item_id, false ); } $discount_tax = 0; // Work out how much tax has been removed as a result of the discount from this coupon. foreach ( $all_discounts[ $coupon_code ] as $item_id => $item_discount_amount ) { $item = $this->get_item( $item_id, false ); if ( 'taxable' !== $item->get_tax_status() || ! kkart_tax_enabled() ) { continue; } $taxes = array_sum( KKART_Tax::calc_tax( $item_discount_amount, KKART_Tax::get_rates( $item->get_tax_class() ), $this->get_prices_include_tax() ) ); if ( 'yes' !== get_option( 'kkart_tax_round_at_subtotal' ) ) { $taxes = kkart_round_tax_total( $taxes ); } $discount_tax += $taxes; if ( $this->get_prices_include_tax() ) { $amount = $amount - $taxes; } } $coupon_item->set_discount( $amount ); $coupon_item->set_discount_tax( $discount_tax ); $this->add_item( $coupon_item ); } } } /** * Add a product line item to the order. This is the only line item type with * its own method because it saves looking up order amounts (costs are added up for you). * * @param KKART_Product $product Product object. * @param int $qty Quantity to add. * @param array $args Args for the added product. * @return int * @throws KKART_Data_Exception Exception thrown if the item cannot be added to the cart. */ public function add_product( $product, $qty = 1, $args = array() ) { if ( $product ) { $default_args = array( 'name' => $product->get_name(), 'tax_class' => $product->get_tax_class(), 'product_id' => $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id(), 'variation_id' => $product->is_type( 'variation' ) ? $product->get_id() : 0, 'variation' => $product->is_type( 'variation' ) ? $product->get_attributes() : array(), 'subtotal' => kkart_get_price_excluding_tax( $product, array( 'qty' => $qty ) ), 'total' => kkart_get_price_excluding_tax( $product, array( 'qty' => $qty ) ), 'quantity' => $qty, ); } else { $default_args = array( 'quantity' => $qty, ); } $args = wp_parse_args( $args, $default_args ); // BW compatibility with old args. if ( isset( $args['totals'] ) ) { foreach ( $args['totals'] as $key => $value ) { if ( 'tax' === $key ) { $args['total_tax'] = $value; } elseif ( 'tax_data' === $key ) { $args['taxes'] = $value; } else { $args[ $key ] = $value; } } } $item = new KKART_Order_Item_Product(); $item->set_props( $args ); $item->set_backorder_meta(); $item->set_order_id( $this->get_id() ); $item->save(); $this->add_item( $item ); delete_transient( 'kkart_order_' . $this->get_id() . '_needs_processing' ); return $item->get_id(); } /* |-------------------------------------------------------------------------- | Payment Token Handling |-------------------------------------------------------------------------- | | Payment tokens are hashes used to take payments by certain gateways. | */ /** * Add a payment token to an order * * @since 2.6 * @param KKART_Payment_Token $token Payment token object. * @return boolean|int The new token ID or false if it failed. */ public function add_payment_token( $token ) { if ( empty( $token ) || ! ( $token instanceof KKART_Payment_Token ) ) { return false; } $token_ids = $this->data_store->get_payment_token_ids( $this ); $token_ids[] = $token->get_id(); $this->data_store->update_payment_token_ids( $this, $token_ids ); do_action( 'kkart_payment_token_added_to_order', $this->get_id(), $token->get_id(), $token, $token_ids ); return $token->get_id(); } /** * Returns a list of all payment tokens associated with the current order * * @since 2.6 * @return array An array of payment token objects */ public function get_payment_tokens() { return $this->data_store->get_payment_token_ids( $this ); } /* |-------------------------------------------------------------------------- | Calculations. |-------------------------------------------------------------------------- | | These methods calculate order totals and taxes based on the current data. | */ /** * Calculate shipping total. * * @since 2.2 * @return float */ public function calculate_shipping() { $shipping_total = 0; foreach ( $this->get_shipping_methods() as $shipping ) { $shipping_total += $shipping->get_total(); } $this->set_shipping_total( $shipping_total ); $this->save(); return $this->get_shipping_total(); } /** * Get all tax classes for items in the order. * * @since 2.6.3 * @return array */ public function get_items_tax_classes() { $found_tax_classes = array(); foreach ( $this->get_items() as $item ) { if ( is_callable( array( $item, 'get_tax_status' ) ) && in_array( $item->get_tax_status(), array( 'taxable', 'shipping' ), true ) ) { $found_tax_classes[] = $item->get_tax_class(); } } return array_unique( $found_tax_classes ); } /** * Get tax location for this order. * * @since 3.2.0 * @param array $args array Override the location. * @return array */ protected function get_tax_location( $args = array() ) { $tax_based_on = get_option( 'kkart_tax_based_on' ); if ( 'shipping' === $tax_based_on && ! $this->get_shipping_country() ) { $tax_based_on = 'billing'; } $args = wp_parse_args( $args, array( 'country' => 'billing' === $tax_based_on ? $this->get_billing_country() : $this->get_shipping_country(), 'state' => 'billing' === $tax_based_on ? $this->get_billing_state() : $this->get_shipping_state(), 'postcode' => 'billing' === $tax_based_on ? $this->get_billing_postcode() : $this->get_shipping_postcode(), 'city' => 'billing' === $tax_based_on ? $this->get_billing_city() : $this->get_shipping_city(), ) ); // Default to base. if ( 'base' === $tax_based_on || empty( $args['country'] ) ) { $args['country'] = KKART()->countries->get_base_country(); $args['state'] = KKART()->countries->get_base_state(); $args['postcode'] = KKART()->countries->get_base_postcode(); $args['city'] = KKART()->countries->get_base_city(); } return apply_filters( 'kkart_order_get_tax_location', $args, $this ); } /** * Calculate taxes for all line items and shipping, and store the totals and tax rows. * * If by default the taxes are based on the shipping address and the current order doesn't * have any, it would use the billing address rather than using the Shopping base location. * * Will use the base country unless customer addresses are set. * * @param array $args Added in 3.0.0 to pass things like location. */ public function calculate_taxes( $args = array() ) { do_action( 'kkart_order_before_calculate_taxes', $args, $this ); $calculate_tax_for = $this->get_tax_location( $args ); $shipping_tax_class = get_option( 'kkart_shipping_tax_class' ); if ( 'inherit' === $shipping_tax_class ) { $found_classes = array_intersect( array_merge( array( '' ), KKART_Tax::get_tax_class_slugs() ), $this->get_items_tax_classes() ); $shipping_tax_class = count( $found_classes ) ? current( $found_classes ) : false; } $is_vat_exempt = apply_filters( 'kkart_order_is_vat_exempt', 'yes' === $this->get_meta( 'is_vat_exempt' ), $this ); // Trigger tax recalculation for all items. foreach ( $this->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) { if ( ! $is_vat_exempt ) { $item->calculate_taxes( $calculate_tax_for ); } else { $item->set_taxes( false ); } } foreach ( $this->get_shipping_methods() as $item_id => $item ) { if ( false !== $shipping_tax_class && ! $is_vat_exempt ) { $item->calculate_taxes( array_merge( $calculate_tax_for, array( 'tax_class' => $shipping_tax_class ) ) ); } else { $item->set_taxes( false ); } } $this->update_taxes(); } /** * Calculate fees for all line items. * * @return float Fee total. */ public function get_total_fees() { return array_reduce( $this->get_fees(), function( $carry, $item ) { return $carry + $item->get_total(); } ); } /** * Update tax lines for the order based on the line item taxes themselves. */ public function update_taxes() { $cart_taxes = array(); $shipping_taxes = array(); $existing_taxes = $this->get_taxes(); $saved_rate_ids = array(); foreach ( $this->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) { $taxes = $item->get_taxes(); foreach ( $taxes['total'] as $tax_rate_id => $tax ) { $tax_amount = $this->round_line_tax( $tax, false ); $cart_taxes[ $tax_rate_id ] = isset( $cart_taxes[ $tax_rate_id ] ) ? $cart_taxes[ $tax_rate_id ] + $tax_amount : $tax_amount; } } foreach ( $this->get_shipping_methods() as $item_id => $item ) { $taxes = $item->get_taxes(); foreach ( $taxes['total'] as $tax_rate_id => $tax ) { $tax_amount = (float) $tax; if ( 'yes' !== get_option( 'kkart_tax_round_at_subtotal' ) ) { $tax_amount = kkart_round_tax_total( $tax_amount ); } $shipping_taxes[ $tax_rate_id ] = isset( $shipping_taxes[ $tax_rate_id ] ) ? $shipping_taxes[ $tax_rate_id ] + $tax_amount : $tax_amount; } } foreach ( $existing_taxes as $tax ) { // Remove taxes which no longer exist for cart/shipping. if ( ( ! array_key_exists( $tax->get_rate_id(), $cart_taxes ) && ! array_key_exists( $tax->get_rate_id(), $shipping_taxes ) ) || in_array( $tax->get_rate_id(), $saved_rate_ids, true ) ) { $this->remove_item( $tax->get_id() ); continue; } $saved_rate_ids[] = $tax->get_rate_id(); $tax->set_tax_total( isset( $cart_taxes[ $tax->get_rate_id() ] ) ? $cart_taxes[ $tax->get_rate_id() ] : 0 ); $tax->set_shipping_tax_total( ! empty( $shipping_taxes[ $tax->get_rate_id() ] ) ? $shipping_taxes[ $tax->get_rate_id() ] : 0 ); $tax->save(); } $new_rate_ids = wp_parse_id_list( array_diff( array_keys( $cart_taxes + $shipping_taxes ), $saved_rate_ids ) ); // New taxes. foreach ( $new_rate_ids as $tax_rate_id ) { $item = new KKART_Order_Item_Tax(); $item->set_rate( $tax_rate_id ); $item->set_tax_total( isset( $cart_taxes[ $tax_rate_id ] ) ? $cart_taxes[ $tax_rate_id ] : 0 ); $item->set_shipping_tax_total( ! empty( $shipping_taxes[ $tax_rate_id ] ) ? $shipping_taxes[ $tax_rate_id ] : 0 ); $this->add_item( $item ); } $this->set_shipping_tax( array_sum( $shipping_taxes ) ); $this->set_cart_tax( array_sum( $cart_taxes ) ); $this->save(); } /** * Helper function. * If you add all items in this order in cart again, this would be the cart subtotal (assuming all other settings are same). * * @return float Cart subtotal. */ protected function get_cart_subtotal_for_order() { return kkart_remove_number_precision( $this->get_rounded_items_total( $this->get_values_for_total( 'subtotal' ) ) ); } /** * Helper function. * If you add all items in this order in cart again, this would be the cart total (assuming all other settings are same). * * @return float Cart total. */ protected function get_cart_total_for_order() { return kkart_remove_number_precision( $this->get_rounded_items_total( $this->get_values_for_total( 'total' ) ) ); } /** * Calculate totals by looking at the contents of the order. Stores the totals and returns the orders final total. * * @since 2.2 * @param bool $and_taxes Calc taxes if true. * @return float calculated grand total. */ public function calculate_totals( $and_taxes = true ) { do_action( 'kkart_order_before_calculate_totals', $and_taxes, $this ); $fees_total = 0; $shipping_total = 0; $cart_subtotal_tax = 0; $cart_total_tax = 0; $cart_subtotal = $this->get_cart_subtotal_for_order(); $cart_total = $this->get_cart_total_for_order(); // Sum shipping costs. foreach ( $this->get_shipping_methods() as $shipping ) { $shipping_total += NumberUtil::round( $shipping->get_total(), kkart_get_price_decimals() ); } $this->set_shipping_total( $shipping_total ); // Sum fee costs. foreach ( $this->get_fees() as $item ) { $fee_total = $item->get_total(); if ( 0 > $fee_total ) { $max_discount = NumberUtil::round( $cart_total + $fees_total + $shipping_total, kkart_get_price_decimals() ) * -1; if ( $fee_total < $max_discount && 0 > $max_discount ) { $item->set_total( $max_discount ); } } $fees_total += $item->get_total(); } // Calculate taxes for items, shipping, discounts. Note; this also triggers save(). if ( $and_taxes ) { $this->calculate_taxes(); } // Sum taxes again so we can work out how much tax was discounted. This uses original values, not those possibly rounded to 2dp. foreach ( $this->get_items() as $item ) { $taxes = $item->get_taxes(); foreach ( $taxes['total'] as $tax_rate_id => $tax ) { $cart_total_tax += (float) $tax; } foreach ( $taxes['subtotal'] as $tax_rate_id => $tax ) { $cart_subtotal_tax += (float) $tax; } } $this->set_discount_total( NumberUtil::round( $cart_subtotal - $cart_total, kkart_get_price_decimals() ) ); $this->set_discount_tax( kkart_round_tax_total( $cart_subtotal_tax - $cart_total_tax ) ); $this->set_total( NumberUtil::round( $cart_total + $fees_total + $this->get_shipping_total() + $this->get_cart_tax() + $this->get_shipping_tax(), kkart_get_price_decimals() ) ); do_action( 'kkart_order_after_calculate_totals', $and_taxes, $this ); $this->save(); return $this->get_total(); } /** * Get item subtotal - this is the cost before discount. * * @param object $item Item to get total from. * @param bool $inc_tax (default: false). * @param bool $round (default: true). * @return float */ public function get_item_subtotal( $item, $inc_tax = false, $round = true ) { $subtotal = 0; if ( is_callable( array( $item, 'get_subtotal' ) ) && $item->get_quantity() ) { if ( $inc_tax ) { $subtotal = ( $item->get_subtotal() + $item->get_subtotal_tax() ) / $item->get_quantity(); } else { $subtotal = floatval( $item->get_subtotal() ) / $item->get_quantity(); } $subtotal = $round ? number_format( (float) $subtotal, kkart_get_price_decimals(), '.', '' ) : $subtotal; } return apply_filters( 'kkart_order_amount_item_subtotal', $subtotal, $this, $item, $inc_tax, $round ); } /** * Get line subtotal - this is the cost before discount. * * @param object $item Item to get total from. * @param bool $inc_tax (default: false). * @param bool $round (default: true). * @return float */ public function get_line_subtotal( $item, $inc_tax = false, $round = true ) { $subtotal = 0; if ( is_callable( array( $item, 'get_subtotal' ) ) ) { if ( $inc_tax ) { $subtotal = $item->get_subtotal() + $item->get_subtotal_tax(); } else { $subtotal = $item->get_subtotal(); } $subtotal = $round ? NumberUtil::round( $subtotal, kkart_get_price_decimals() ) : $subtotal; } return apply_filters( 'kkart_order_amount_line_subtotal', $subtotal, $this, $item, $inc_tax, $round ); } /** * Calculate item cost - useful for gateways. * * @param object $item Item to get total from. * @param bool $inc_tax (default: false). * @param bool $round (default: true). * @return float */ public function get_item_total( $item, $inc_tax = false, $round = true ) { $total = 0; if ( is_callable( array( $item, 'get_total' ) ) && $item->get_quantity() ) { if ( $inc_tax ) { $total = ( $item->get_total() + $item->get_total_tax() ) / $item->get_quantity(); } else { $total = floatval( $item->get_total() ) / $item->get_quantity(); } $total = $round ? NumberUtil::round( $total, kkart_get_price_decimals() ) : $total; } return apply_filters( 'kkart_order_amount_item_total', $total, $this, $item, $inc_tax, $round ); } /** * Calculate line total - useful for gateways. * * @param object $item Item to get total from. * @param bool $inc_tax (default: false). * @param bool $round (default: true). * @return float */ public function get_line_total( $item, $inc_tax = false, $round = true ) { $total = 0; if ( is_callable( array( $item, 'get_total' ) ) ) { // Check if we need to add line tax to the line total. $total = $inc_tax ? $item->get_total() + $item->get_total_tax() : $item->get_total(); // Check if we need to round. $total = $round ? NumberUtil::round( $total, kkart_get_price_decimals() ) : $total; } return apply_filters( 'kkart_order_amount_line_total', $total, $this, $item, $inc_tax, $round ); } /** * Get item tax - useful for gateways. * * @param mixed $item Item to get total from. * @param bool $round (default: true). * @return float */ public function get_item_tax( $item, $round = true ) { $tax = 0; if ( is_callable( array( $item, 'get_total_tax' ) ) && $item->get_quantity() ) { $tax = $item->get_total_tax() / $item->get_quantity(); $tax = $round ? kkart_round_tax_total( $tax ) : $tax; } return apply_filters( 'kkart_order_amount_item_tax', $tax, $item, $round, $this ); } /** * Get line tax - useful for gateways. * * @param mixed $item Item to get total from. * @return float */ public function get_line_tax( $item ) { return apply_filters( 'kkart_order_amount_line_tax', is_callable( array( $item, 'get_total_tax' ) ) ? kkart_round_tax_total( $item->get_total_tax() ) : 0, $item, $this ); } /** * Gets line subtotal - formatted for display. * * @param object $item Item to get total from. * @param string $tax_display Incl or excl tax display mode. * @return string */ public function get_formatted_line_subtotal( $item, $tax_display = '' ) { $tax_display = $tax_display ? $tax_display : get_option( 'kkart_tax_display_cart' ); if ( 'excl' === $tax_display ) { $ex_tax_label = $this->get_prices_include_tax() ? 1 : 0; $subtotal = kkart_price( $this->get_line_subtotal( $item ), array( 'ex_tax_label' => $ex_tax_label, 'currency' => $this->get_currency(), ) ); } else { $subtotal = kkart_price( $this->get_line_subtotal( $item, true ), array( 'currency' => $this->get_currency() ) ); } return apply_filters( 'kkart_order_formatted_line_subtotal', $subtotal, $item, $this ); } /** * Gets order total - formatted for display. * * @return string */ public function get_formatted_order_total() { $formatted_total = kkart_price( $this->get_total(), array( 'currency' => $this->get_currency() ) ); return apply_filters( 'kkart_get_formatted_order_total', $formatted_total, $this ); } /** * Gets subtotal - subtotal is shown before discounts, but with localised taxes. * * @param bool $compound (default: false). * @param string $tax_display (default: the tax_display_cart value). * @return string */ public function get_subtotal_to_display( $compound = false, $tax_display = '' ) { $tax_display = $tax_display ? $tax_display : get_option( 'kkart_tax_display_cart' ); $subtotal = $this->get_cart_subtotal_for_order(); if ( ! $compound ) { if ( 'incl' === $tax_display ) { $subtotal_taxes = 0; foreach ( $this->get_items() as $item ) { $subtotal_taxes += self::round_line_tax( $item->get_subtotal_tax(), false ); } $subtotal += kkart_round_tax_total( $subtotal_taxes ); } $subtotal = kkart_price( $subtotal, array( 'currency' => $this->get_currency() ) ); if ( 'excl' === $tax_display && $this->get_prices_include_tax() && kkart_tax_enabled() ) { $subtotal .= ' ' . KKART()->countries->ex_tax_or_vat() . ''; } } else { if ( 'incl' === $tax_display ) { return ''; } // Add Shipping Costs. $subtotal += $this->get_shipping_total(); // Remove non-compound taxes. foreach ( $this->get_taxes() as $tax ) { if ( $tax->is_compound() ) { continue; } $subtotal = $subtotal + $tax->get_tax_total() + $tax->get_shipping_tax_total(); } // Remove discounts. $subtotal = $subtotal - $this->get_total_discount(); $subtotal = kkart_price( $subtotal, array( 'currency' => $this->get_currency() ) ); } return apply_filters( 'kkart_order_subtotal_to_display', $subtotal, $compound, $this ); } /** * Gets shipping (formatted). * * @param string $tax_display Excl or incl tax display mode. * @return string */ public function get_shipping_to_display( $tax_display = '' ) { $tax_display = $tax_display ? $tax_display : get_option( 'kkart_tax_display_cart' ); if ( 0 < abs( (float) $this->get_shipping_total() ) ) { if ( 'excl' === $tax_display ) { // Show shipping excluding tax. $shipping = kkart_price( $this->get_shipping_total(), array( 'currency' => $this->get_currency() ) ); if ( (float) $this->get_shipping_tax() > 0 && $this->get_prices_include_tax() ) { $shipping .= apply_filters( 'kkart_order_shipping_to_display_tax_label', ' ' . KKART()->countries->ex_tax_or_vat() . '', $this, $tax_display ); } } else { // Show shipping including tax. $shipping = kkart_price( $this->get_shipping_total() + $this->get_shipping_tax(), array( 'currency' => $this->get_currency() ) ); if ( (float) $this->get_shipping_tax() > 0 && ! $this->get_prices_include_tax() ) { $shipping .= apply_filters( 'kkart_order_shipping_to_display_tax_label', ' ' . KKART()->countries->inc_tax_or_vat() . '', $this, $tax_display ); } } /* translators: %s: method */ $shipping .= apply_filters( 'kkart_order_shipping_to_display_shipped_via', ' ' . sprintf( __( 'via %s', 'kkart' ), $this->get_shipping_method() ) . '', $this ); } elseif ( $this->get_shipping_method() ) { $shipping = $this->get_shipping_method(); } else { $shipping = __( 'Free!', 'kkart' ); } return apply_filters( 'kkart_order_shipping_to_display', $shipping, $this, $tax_display ); } /** * Get the discount amount (formatted). * * @since 2.3.0 * @param string $tax_display Excl or incl tax display mode. * @return string */ public function get_discount_to_display( $tax_display = '' ) { $tax_display = $tax_display ? $tax_display : get_option( 'kkart_tax_display_cart' ); return apply_filters( 'kkart_order_discount_to_display', kkart_price( $this->get_total_discount( 'excl' === $tax_display && 'excl' === get_option( 'kkart_tax_display_cart' ) ), array( 'currency' => $this->get_currency() ) ), $this ); } /** * Add total row for subtotal. * * @param array $total_rows Reference to total rows array. * @param string $tax_display Excl or incl tax display mode. */ protected function add_order_item_totals_subtotal_row( &$total_rows, $tax_display ) { $subtotal = $this->get_subtotal_to_display( false, $tax_display ); if ( $subtotal ) { $total_rows['cart_subtotal'] = array( 'label' => __( 'Subtotal:', 'kkart' ), 'value' => $subtotal, ); } } /** * Add total row for discounts. * * @param array $total_rows Reference to total rows array. * @param string $tax_display Excl or incl tax display mode. */ protected function add_order_item_totals_discount_row( &$total_rows, $tax_display ) { if ( $this->get_total_discount() > 0 ) { $total_rows['discount'] = array( 'label' => __( 'Discount:', 'kkart' ), 'value' => '-' . $this->get_discount_to_display( $tax_display ), ); } } /** * Add total row for shipping. * * @param array $total_rows Reference to total rows array. * @param string $tax_display Excl or incl tax display mode. */ protected function add_order_item_totals_shipping_row( &$total_rows, $tax_display ) { if ( $this->get_shipping_method() ) { $total_rows['shipping'] = array( 'label' => __( 'Shipping:', 'kkart' ), 'value' => $this->get_shipping_to_display( $tax_display ), ); } } /** * Add total row for fees. * * @param array $total_rows Reference to total rows array. * @param string $tax_display Excl or incl tax display mode. */ protected function add_order_item_totals_fee_rows( &$total_rows, $tax_display ) { $fees = $this->get_fees(); if ( $fees ) { foreach ( $fees as $id => $fee ) { if ( apply_filters( 'kkart_get_order_item_totals_excl_free_fees', empty( $fee['line_total'] ) && empty( $fee['line_tax'] ), $id ) ) { continue; } $total_rows[ 'fee_' . $fee->get_id() ] = array( 'label' => $fee->get_name() . ':', 'value' => kkart_price( 'excl' === $tax_display ? $fee->get_total() : $fee->get_total() + $fee->get_total_tax(), array( 'currency' => $this->get_currency() ) ), ); } } } /** * Add total row for taxes. * * @param array $total_rows Reference to total rows array. * @param string $tax_display Excl or incl tax display mode. */ protected function add_order_item_totals_tax_rows( &$total_rows, $tax_display ) { // Tax for tax exclusive prices. if ( 'excl' === $tax_display && kkart_tax_enabled() ) { if ( 'itemized' === get_option( 'kkart_tax_total_display' ) ) { foreach ( $this->get_tax_totals() as $code => $tax ) { $total_rows[ sanitize_title( $code ) ] = array( 'label' => $tax->label . ':', 'value' => $tax->formatted_amount, ); } } else { $total_rows['tax'] = array( 'label' => KKART()->countries->tax_or_vat() . ':', 'value' => kkart_price( $this->get_total_tax(), array( 'currency' => $this->get_currency() ) ), ); } } } /** * Add total row for grand total. * * @param array $total_rows Reference to total rows array. * @param string $tax_display Excl or incl tax display mode. */ protected function add_order_item_totals_total_row( &$total_rows, $tax_display ) { $total_rows['order_total'] = array( 'label' => __( 'Total:', 'kkart' ), 'value' => $this->get_formatted_order_total( $tax_display ), ); } /** * Get totals for display on pages and in emails. * * @param mixed $tax_display Excl or incl tax display mode. * @return array */ public function get_order_item_totals( $tax_display = '' ) { $tax_display = $tax_display ? $tax_display : get_option( 'kkart_tax_display_cart' ); $total_rows = array(); $this->add_order_item_totals_subtotal_row( $total_rows, $tax_display ); $this->add_order_item_totals_discount_row( $total_rows, $tax_display ); $this->add_order_item_totals_shipping_row( $total_rows, $tax_display ); $this->add_order_item_totals_fee_rows( $total_rows, $tax_display ); $this->add_order_item_totals_tax_rows( $total_rows, $tax_display ); $this->add_order_item_totals_total_row( $total_rows, $tax_display ); return apply_filters( 'kkart_get_order_item_totals', $total_rows, $this, $tax_display ); } /* |-------------------------------------------------------------------------- | Conditionals |-------------------------------------------------------------------------- | | Checks if a condition is true or false. | */ /** * Checks the order status against a passed in status. * * @param array|string $status Status to check. * @return bool */ public function has_status( $status ) { return apply_filters( 'kkart_order_has_status', ( is_array( $status ) && in_array( $this->get_status(), $status, true ) ) || $this->get_status() === $status, $this, $status ); } /** * Check whether this order has a specific shipping method or not. * * @param string $method_id Method ID to check. * @return bool */ public function has_shipping_method( $method_id ) { foreach ( $this->get_shipping_methods() as $shipping_method ) { if ( strpos( $shipping_method->get_method_id(), $method_id ) === 0 ) { return true; } } return false; } /** * Returns true if the order contains a free product. * * @since 2.5.0 * @return bool */ public function has_free_item() { foreach ( $this->get_items() as $item ) { if ( ! $item->get_total() ) { return true; } } return false; } } PK!mr(abstracts/abstract-kkart-log-handler.phpnu[ $timestamp, 'level' => $level, 'message' => $message, 'context' => $context, ) ); } } PK!1yy,abstracts/class-kkart-background-process.phpnu[options; $column = 'option_name'; if ( is_multisite() ) { $table = $wpdb->sitemeta; $column = 'meta_key'; } $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%'; $count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$table} WHERE {$column} LIKE %s", $key ) ); // @codingStandardsIgnoreLine. return ! ( $count > 0 ); } /** * Get batch. * * @return stdClass Return the first batch from the queue. */ protected function get_batch() { global $wpdb; $table = $wpdb->options; $column = 'option_name'; $key_column = 'option_id'; $value_column = 'option_value'; if ( is_multisite() ) { $table = $wpdb->sitemeta; $column = 'meta_key'; $key_column = 'meta_id'; $value_column = 'meta_value'; } $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%'; $query = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE {$column} LIKE %s ORDER BY {$key_column} ASC LIMIT 1", $key ) ); // @codingStandardsIgnoreLine. $batch = new stdClass(); $batch->key = $query->$column; $batch->data = array_filter( (array) maybe_unserialize( $query->$value_column ) ); return $batch; } /** * See if the batch limit has been exceeded. * * @return bool */ protected function batch_limit_exceeded() { return $this->time_exceeded() || $this->memory_exceeded(); } /** * Handle. * * Pass each queue item to the task handler, while remaining * within server memory and time limit constraints. */ protected function handle() { $this->lock_process(); do { $batch = $this->get_batch(); foreach ( $batch->data as $key => $value ) { $task = $this->task( $value ); if ( false !== $task ) { $batch->data[ $key ] = $task; } else { unset( $batch->data[ $key ] ); } if ( $this->batch_limit_exceeded() ) { // Batch limits reached. break; } } // Update or delete current batch. if ( ! empty( $batch->data ) ) { $this->update( $batch->key, $batch->data ); } else { $this->delete( $batch->key ); } } while ( ! $this->batch_limit_exceeded() && ! $this->is_queue_empty() ); $this->unlock_process(); // Start next batch or complete process. if ( ! $this->is_queue_empty() ) { $this->dispatch(); } else { $this->complete(); } } /** * Get memory limit. * * @return int */ protected function get_memory_limit() { if ( function_exists( 'ini_get' ) ) { $memory_limit = ini_get( 'memory_limit' ); } else { // Sensible default. $memory_limit = '128M'; } if ( ! $memory_limit || -1 === intval( $memory_limit ) ) { // Unlimited, set to 32GB. $memory_limit = '32G'; } return wp_convert_hr_to_bytes( $memory_limit ); } /** * Schedule cron healthcheck. * * @param array $schedules Schedules. * @return array */ public function schedule_cron_healthcheck( $schedules ) { $interval = apply_filters( $this->identifier . '_cron_interval', 5 ); if ( property_exists( $this, 'cron_interval' ) ) { $interval = apply_filters( $this->identifier . '_cron_interval', $this->cron_interval ); } // Adds every 5 minutes to the existing schedules. $schedules[ $this->identifier . '_cron_interval' ] = array( 'interval' => MINUTE_IN_SECONDS * $interval, /* translators: %d: interval */ 'display' => sprintf( __( 'Every %d minutes', 'kkart' ), $interval ), ); return $schedules; } /** * Delete all batches. * * @return KKART_Background_Process */ public function delete_all_batches() { global $wpdb; $table = $wpdb->options; $column = 'option_name'; if ( is_multisite() ) { $table = $wpdb->sitemeta; $column = 'meta_key'; } $key = $wpdb->esc_like( $this->identifier . '_batch_' ) . '%'; $wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE {$column} LIKE %s", $key ) ); // @codingStandardsIgnoreLine. return $this; } /** * Kill process. * * Stop processing queue items, clear cronjob and delete all batches. */ public function kill_process() { if ( ! $this->is_queue_empty() ) { $this->delete_all_batches(); wp_clear_scheduled_hook( $this->cron_hook_identifier ); } } } PK!ly y -abstracts/abstract-kkart-deprecated-hooks.phpnu[deprecated_hooks ); array_walk( $new_hooks, array( $this, 'hook_in' ) ); } /** * Hook into the new hook so we can handle deprecated hooks once fired. * * @param string $hook_name Hook name. */ abstract public function hook_in( $hook_name ); /** * Get old hooks to map to new hook. * * @param string $new_hook New hook name. * @return array */ public function get_old_hooks( $new_hook ) { $old_hooks = isset( $this->deprecated_hooks[ $new_hook ] ) ? $this->deprecated_hooks[ $new_hook ] : array(); $old_hooks = is_array( $old_hooks ) ? $old_hooks : array( $old_hooks ); return $old_hooks; } /** * If the hook is Deprecated, call the old hooks here. */ public function maybe_handle_deprecated_hook() { $new_hook = current_filter(); $old_hooks = $this->get_old_hooks( $new_hook ); $new_callback_args = func_get_args(); $return_value = $new_callback_args[0]; foreach ( $old_hooks as $old_hook ) { $return_value = $this->handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ); } return $return_value; } /** * If the old hook is in-use, trigger it. * * @param string $new_hook New hook name. * @param string $old_hook Old hook name. * @param array $new_callback_args New callback args. * @param mixed $return_value Returned value. * @return mixed */ abstract public function handle_deprecated_hook( $new_hook, $old_hook, $new_callback_args, $return_value ); /** * Get deprecated version. * * @param string $old_hook Old hook name. * @return string */ protected function get_deprecated_version( $old_hook ) { return ! empty( $this->deprecated_version[ $old_hook ] ) ? $this->deprecated_version[ $old_hook ] : Constants::get_constant( 'KKART_VERSION' ); } /** * Display a deprecated notice for old hooks. * * @param string $old_hook Old hook. * @param string $new_hook New hook. */ protected function display_notice( $old_hook, $new_hook ) { kkart_deprecated_hook( esc_html( $old_hook ), esc_html( $this->get_deprecated_version( $old_hook ) ), esc_html( $new_hook ) ); } /** * Fire off a legacy hook with it's args. * * @param string $old_hook Old hook name. * @param array $new_callback_args New callback args. * @return mixed */ abstract protected function trigger_hook( $old_hook, $new_callback_args ); } PK!9w0w0#abstracts/abstract-kkart-widget.phpnu[ $this->widget_cssclass, 'description' => $this->widget_description, 'customize_selective_refresh' => true, ); parent::__construct( $this->widget_id, $this->widget_name, $widget_ops ); add_action( 'save_post', array( $this, 'flush_widget_cache' ) ); add_action( 'deleted_post', array( $this, 'flush_widget_cache' ) ); add_action( 'switch_theme', array( $this, 'flush_widget_cache' ) ); } /** * Get cached widget. * * @param array $args Arguments. * @return bool true if the widget is cached otherwise false */ public function get_cached_widget( $args ) { // Don't get cache if widget_id doesn't exists. if ( empty( $args['widget_id'] ) ) { return false; } $cache = wp_cache_get( $this->get_widget_id_for_cache( $this->widget_id ), 'widget' ); if ( ! is_array( $cache ) ) { $cache = array(); } if ( isset( $cache[ $this->get_widget_id_for_cache( $args['widget_id'] ) ] ) ) { echo $cache[ $this->get_widget_id_for_cache( $args['widget_id'] ) ]; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped return true; } return false; } /** * Cache the widget. * * @param array $args Arguments. * @param string $content Content. * @return string the content that was cached */ public function cache_widget( $args, $content ) { // Don't set any cache if widget_id doesn't exist. if ( empty( $args['widget_id'] ) ) { return $content; } $cache = wp_cache_get( $this->get_widget_id_for_cache( $this->widget_id ), 'widget' ); if ( ! is_array( $cache ) ) { $cache = array(); } $cache[ $this->get_widget_id_for_cache( $args['widget_id'] ) ] = $content; wp_cache_set( $this->get_widget_id_for_cache( $this->widget_id ), $cache, 'widget' ); return $content; } /** * Flush the cache. */ public function flush_widget_cache() { foreach ( array( 'https', 'http' ) as $scheme ) { wp_cache_delete( $this->get_widget_id_for_cache( $this->widget_id, $scheme ), 'widget' ); } } /** * Get this widgets title. * * @param array $instance Array of instance options. * @return string */ protected function get_instance_title( $instance ) { if ( isset( $instance['title'] ) ) { return $instance['title']; } if ( isset( $this->settings, $this->settings['title'], $this->settings['title']['std'] ) ) { return $this->settings['title']['std']; } return ''; } /** * Output the html at the start of a widget. * * @param array $args Arguments. * @param array $instance Instance. */ public function widget_start( $args, $instance ) { echo $args['before_widget']; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped $title = apply_filters( 'widget_title', $this->get_instance_title( $instance ), $instance, $this->id_base ); if ( $title ) { echo $args['before_title'] . $title . $args['after_title']; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped } } /** * Output the html at the end of a widget. * * @param array $args Arguments. */ public function widget_end( $args ) { echo $args['after_widget']; // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped } /** * Updates a particular instance of a widget. * * @see WP_Widget->update * @param array $new_instance New instance. * @param array $old_instance Old instance. * @return array */ public function update( $new_instance, $old_instance ) { $instance = $old_instance; if ( empty( $this->settings ) ) { return $instance; } // Loop settings and get values to save. foreach ( $this->settings as $key => $setting ) { if ( ! isset( $setting['type'] ) ) { continue; } // Format the value based on settings type. switch ( $setting['type'] ) { case 'number': $instance[ $key ] = absint( $new_instance[ $key ] ); if ( isset( $setting['min'] ) && '' !== $setting['min'] ) { $instance[ $key ] = max( $instance[ $key ], $setting['min'] ); } if ( isset( $setting['max'] ) && '' !== $setting['max'] ) { $instance[ $key ] = min( $instance[ $key ], $setting['max'] ); } break; case 'textarea': $instance[ $key ] = wp_kses( trim( wp_unslash( $new_instance[ $key ] ) ), wp_kses_allowed_html( 'post' ) ); break; case 'checkbox': $instance[ $key ] = empty( $new_instance[ $key ] ) ? 0 : 1; break; default: $instance[ $key ] = isset( $new_instance[ $key ] ) ? sanitize_text_field( $new_instance[ $key ] ) : $setting['std']; break; } /** * Sanitize the value of a setting. */ $instance[ $key ] = apply_filters( 'kkart_widget_settings_sanitize_option', $instance[ $key ], $new_instance, $key, $setting ); } $this->flush_widget_cache(); return $instance; } /** * Outputs the settings update form. * * @see WP_Widget->form * * @param array $instance Instance. */ public function form( $instance ) { if ( empty( $this->settings ) ) { return; } foreach ( $this->settings as $key => $setting ) { $class = isset( $setting['class'] ) ? $setting['class'] : ''; $value = isset( $instance[ $key ] ) ? $instance[ $key ] : $setting['std']; switch ( $setting['type'] ) { case 'text': ?>

/>

slug, $queried_object->taxonomy ); } // Min/Max. if ( isset( $_GET['min_price'] ) ) { $link = add_query_arg( 'min_price', kkart_clean( wp_unslash( $_GET['min_price'] ) ), $link ); } if ( isset( $_GET['max_price'] ) ) { $link = add_query_arg( 'max_price', kkart_clean( wp_unslash( $_GET['max_price'] ) ), $link ); } // Order by. if ( isset( $_GET['orderby'] ) ) { $link = add_query_arg( 'orderby', kkart_clean( wp_unslash( $_GET['orderby'] ) ), $link ); } /** * Search Arg. * To support quote characters, first they are decoded from " entities, then URL encoded. */ if ( get_search_query() ) { $link = add_query_arg( 's', rawurlencode( htmlspecialchars_decode( get_search_query() ) ), $link ); } // Post Type Arg. if ( isset( $_GET['post_type'] ) ) { $link = add_query_arg( 'post_type', kkart_clean( wp_unslash( $_GET['post_type'] ) ), $link ); // Prevent post type and page id when pretty permalinks are disabled. if ( is_shop() ) { $link = remove_query_arg( 'page_id', $link ); } } // Min Rating Arg. if ( isset( $_GET['rating_filter'] ) ) { $link = add_query_arg( 'rating_filter', kkart_clean( wp_unslash( $_GET['rating_filter'] ) ), $link ); } // All current filters. if ( $_chosen_attributes = KKART_Query::get_layered_nav_chosen_attributes() ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.Found, WordPress.CodeAnalysis.AssignmentInCondition.Found foreach ( $_chosen_attributes as $name => $data ) { $filter_name = kkart_attribute_taxonomy_slug( $name ); if ( ! empty( $data['terms'] ) ) { $link = add_query_arg( 'filter_' . $filter_name, implode( ',', $data['terms'] ), $link ); } if ( 'or' === $data['query_type'] ) { $link = add_query_arg( 'query_type_' . $filter_name, 'or', $link ); } } } return apply_filters( 'kkart_widget_get_current_page_url', $link, $this ); } /** * Get widget id plus scheme/protocol to prevent serving mixed content from (persistently) cached widgets. * * @since 3.4.0 * @param string $widget_id Id of the cached widget. * @param string $scheme Scheme for the widget id. * @return string Widget id including scheme/protocol. */ protected function get_widget_id_for_cache( $widget_id, $scheme = '' ) { if ( $scheme ) { $widget_id_for_cache = $widget_id . '-' . $scheme; } else { $widget_id_for_cache = $widget_id . '-' . ( is_ssl() ? 'https' : 'http' ); } return apply_filters( 'kkart_cached_widget_id', $widget_id_for_cache ); } } PK!u$abstracts/abstract-kkart-product.phpnu[ '', 'slug' => '', 'date_created' => null, 'date_modified' => null, 'status' => false, 'featured' => false, 'catalog_visibility' => 'visible', 'description' => '', 'short_description' => '', 'sku' => '', 'price' => '', 'regular_price' => '', 'sale_price' => '', 'date_on_sale_from' => null, 'date_on_sale_to' => null, 'total_sales' => '0', 'tax_status' => 'taxable', 'tax_class' => '', 'manage_stock' => false, 'stock_quantity' => null, 'stock_status' => 'instock', 'backorders' => 'no', 'low_stock_amount' => '', 'sold_individually' => false, 'weight' => '', 'length' => '', 'width' => '', 'height' => '', 'upsell_ids' => array(), 'cross_sell_ids' => array(), 'parent_id' => 0, 'reviews_allowed' => true, 'purchase_note' => '', 'attributes' => array(), 'default_attributes' => array(), 'menu_order' => 0, 'post_password' => '', 'virtual' => false, 'downloadable' => false, 'category_ids' => array(), 'tag_ids' => array(), 'shipping_class_id' => 0, 'downloads' => array(), 'image_id' => '', 'gallery_image_ids' => array(), 'download_limit' => -1, 'download_expiry' => -1, 'rating_counts' => array(), 'average_rating' => 0, 'review_count' => 0, ); /** * Supported features such as 'ajax_add_to_cart'. * * @var array */ protected $supports = array(); /** * Get the product if ID is passed, otherwise the product is new and empty. * This class should NOT be instantiated, but the kkart_get_product() function * should be used. It is possible, but the kkart_get_product() is preferred. * * @param int|KKART_Product|object $product Product to init. */ public function __construct( $product = 0 ) { parent::__construct( $product ); if ( is_numeric( $product ) && $product > 0 ) { $this->set_id( $product ); } elseif ( $product instanceof self ) { $this->set_id( absint( $product->get_id() ) ); } elseif ( ! empty( $product->ID ) ) { $this->set_id( absint( $product->ID ) ); } else { $this->set_object_read( true ); } $this->data_store = KKART_Data_Store::load( 'product-' . $this->get_type() ); if ( $this->get_id() > 0 ) { $this->data_store->read( $this ); } } /** * Get internal type. Should return string and *should be overridden* by child classes. * * The product_type property is deprecated but is used here for BW compatibility with child classes which may be defining product_type and not have a get_type method. * * @since 3.0.0 * @return string */ public function get_type() { return isset( $this->product_type ) ? $this->product_type : 'simple'; } /** * Get product name. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_name( $context = 'view' ) { return $this->get_prop( 'name', $context ); } /** * Get product slug. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_slug( $context = 'view' ) { return $this->get_prop( 'slug', $context ); } /** * Get product created date. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_created( $context = 'view' ) { return $this->get_prop( 'date_created', $context ); } /** * Get product modified date. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_modified( $context = 'view' ) { return $this->get_prop( 'date_modified', $context ); } /** * Get product status. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_status( $context = 'view' ) { return $this->get_prop( 'status', $context ); } /** * If the product is featured. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return boolean */ public function get_featured( $context = 'view' ) { return $this->get_prop( 'featured', $context ); } /** * Get catalog visibility. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_catalog_visibility( $context = 'view' ) { return $this->get_prop( 'catalog_visibility', $context ); } /** * Get product description. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_description( $context = 'view' ) { return $this->get_prop( 'description', $context ); } /** * Get product short description. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_short_description( $context = 'view' ) { return $this->get_prop( 'short_description', $context ); } /** * Get SKU (Stock-keeping unit) - product unique ID. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_sku( $context = 'view' ) { return $this->get_prop( 'sku', $context ); } /** * Returns the product's active price. * * @param string $context What the value is for. Valid values are view and edit. * @return string price */ public function get_price( $context = 'view' ) { return $this->get_prop( 'price', $context ); } /** * Returns the product's regular price. * * @param string $context What the value is for. Valid values are view and edit. * @return string price */ public function get_regular_price( $context = 'view' ) { return $this->get_prop( 'regular_price', $context ); } /** * Returns the product's sale price. * * @param string $context What the value is for. Valid values are view and edit. * @return string price */ public function get_sale_price( $context = 'view' ) { return $this->get_prop( 'sale_price', $context ); } /** * Get date on sale from. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_on_sale_from( $context = 'view' ) { return $this->get_prop( 'date_on_sale_from', $context ); } /** * Get date on sale to. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_on_sale_to( $context = 'view' ) { return $this->get_prop( 'date_on_sale_to', $context ); } /** * Get number total of sales. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_total_sales( $context = 'view' ) { return $this->get_prop( 'total_sales', $context ); } /** * Returns the tax status. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_tax_status( $context = 'view' ) { return $this->get_prop( 'tax_status', $context ); } /** * Returns the tax class. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_tax_class( $context = 'view' ) { return $this->get_prop( 'tax_class', $context ); } /** * Return if product manage stock. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return boolean */ public function get_manage_stock( $context = 'view' ) { return $this->get_prop( 'manage_stock', $context ); } /** * Returns number of items available for sale. * * @param string $context What the value is for. Valid values are view and edit. * @return int|null */ public function get_stock_quantity( $context = 'view' ) { return $this->get_prop( 'stock_quantity', $context ); } /** * Return the stock status. * * @param string $context What the value is for. Valid values are view and edit. * @since 3.0.0 * @return string */ public function get_stock_status( $context = 'view' ) { return $this->get_prop( 'stock_status', $context ); } /** * Get backorders. * * @param string $context What the value is for. Valid values are view and edit. * @since 3.0.0 * @return string yes no or notify */ public function get_backorders( $context = 'view' ) { return $this->get_prop( 'backorders', $context ); } /** * Get low stock amount. * * @param string $context What the value is for. Valid values are view and edit. * @since 3.5.0 * @return int|string Returns empty string if value not set */ public function get_low_stock_amount( $context = 'view' ) { return $this->get_prop( 'low_stock_amount', $context ); } /** * Return if should be sold individually. * * @param string $context What the value is for. Valid values are view and edit. * @since 3.0.0 * @return boolean */ public function get_sold_individually( $context = 'view' ) { return $this->get_prop( 'sold_individually', $context ); } /** * Returns the product's weight. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_weight( $context = 'view' ) { return $this->get_prop( 'weight', $context ); } /** * Returns the product length. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_length( $context = 'view' ) { return $this->get_prop( 'length', $context ); } /** * Returns the product width. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_width( $context = 'view' ) { return $this->get_prop( 'width', $context ); } /** * Returns the product height. * * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_height( $context = 'view' ) { return $this->get_prop( 'height', $context ); } /** * Returns formatted dimensions. * * @param bool $formatted True by default for legacy support - will be false/not set in future versions to return the array only. Use kkart_format_dimensions for formatted versions instead. * @return string|array */ public function get_dimensions( $formatted = true ) { if ( $formatted ) { kkart_deprecated_argument( 'KKART_Product::get_dimensions', '3.0', 'By default, get_dimensions has an argument set to true so that HTML is returned. This is to support the legacy version of the method. To get HTML dimensions, instead use kkart_format_dimensions() function. Pass false to this method to return an array of dimensions. This will be the new default behavior in future versions.' ); return apply_filters( 'kkart_product_dimensions', kkart_format_dimensions( $this->get_dimensions( false ) ), $this ); } return array( 'length' => $this->get_length(), 'width' => $this->get_width(), 'height' => $this->get_height(), ); } /** * Get upsell IDs. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_upsell_ids( $context = 'view' ) { return $this->get_prop( 'upsell_ids', $context ); } /** * Get cross sell IDs. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_cross_sell_ids( $context = 'view' ) { return $this->get_prop( 'cross_sell_ids', $context ); } /** * Get parent ID. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_parent_id( $context = 'view' ) { return $this->get_prop( 'parent_id', $context ); } /** * Return if reviews is allowed. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function get_reviews_allowed( $context = 'view' ) { return $this->get_prop( 'reviews_allowed', $context ); } /** * Get purchase note. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_purchase_note( $context = 'view' ) { return $this->get_prop( 'purchase_note', $context ); } /** * Returns product attributes. * * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_attributes( $context = 'view' ) { return $this->get_prop( 'attributes', $context ); } /** * Get default attributes. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_default_attributes( $context = 'view' ) { return $this->get_prop( 'default_attributes', $context ); } /** * Get menu order. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_menu_order( $context = 'view' ) { return $this->get_prop( 'menu_order', $context ); } /** * Get post password. * * @since 3.6.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_post_password( $context = 'view' ) { return $this->get_prop( 'post_password', $context ); } /** * Get category ids. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_category_ids( $context = 'view' ) { return $this->get_prop( 'category_ids', $context ); } /** * Get tag ids. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_tag_ids( $context = 'view' ) { return $this->get_prop( 'tag_ids', $context ); } /** * Get virtual. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function get_virtual( $context = 'view' ) { return $this->get_prop( 'virtual', $context ); } /** * Returns the gallery attachment ids. * * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_gallery_image_ids( $context = 'view' ) { return $this->get_prop( 'gallery_image_ids', $context ); } /** * Get shipping class ID. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_shipping_class_id( $context = 'view' ) { return $this->get_prop( 'shipping_class_id', $context ); } /** * Get downloads. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_downloads( $context = 'view' ) { return $this->get_prop( 'downloads', $context ); } /** * Get download expiry. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_download_expiry( $context = 'view' ) { return $this->get_prop( 'download_expiry', $context ); } /** * Get downloadable. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function get_downloadable( $context = 'view' ) { return $this->get_prop( 'downloadable', $context ); } /** * Get download limit. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_download_limit( $context = 'view' ) { return $this->get_prop( 'download_limit', $context ); } /** * Get main image ID. * * @since 3.0.0 * @param string $context What the value is for. Valid values are view and edit. * @return string */ public function get_image_id( $context = 'view' ) { return $this->get_prop( 'image_id', $context ); } /** * Get rating count. * * @param string $context What the value is for. Valid values are view and edit. * @return array of counts */ public function get_rating_counts( $context = 'view' ) { return $this->get_prop( 'rating_counts', $context ); } /** * Get average rating. * * @param string $context What the value is for. Valid values are view and edit. * @return float */ public function get_average_rating( $context = 'view' ) { return $this->get_prop( 'average_rating', $context ); } /** * Get review count. * * @param string $context What the value is for. Valid values are view and edit. * @return int */ public function get_review_count( $context = 'view' ) { return $this->get_prop( 'review_count', $context ); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- | | Functions for setting product data. These should not update anything in the | database itself and should only change what is stored in the class | object. */ /** * Set product name. * * @since 3.0.0 * @param string $name Product name. */ public function set_name( $name ) { $this->set_prop( 'name', $name ); } /** * Set product slug. * * @since 3.0.0 * @param string $slug Product slug. */ public function set_slug( $slug ) { $this->set_prop( 'slug', $slug ); } /** * Set product created date. * * @since 3.0.0 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. */ public function set_date_created( $date = null ) { $this->set_date_prop( 'date_created', $date ); } /** * Set product modified date. * * @since 3.0.0 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. */ public function set_date_modified( $date = null ) { $this->set_date_prop( 'date_modified', $date ); } /** * Set product status. * * @since 3.0.0 * @param string $status Product status. */ public function set_status( $status ) { $this->set_prop( 'status', $status ); } /** * Set if the product is featured. * * @since 3.0.0 * @param bool|string $featured Whether the product is featured or not. */ public function set_featured( $featured ) { $this->set_prop( 'featured', kkart_string_to_bool( $featured ) ); } /** * Set catalog visibility. * * @since 3.0.0 * @throws KKART_Data_Exception Throws exception when invalid data is found. * @param string $visibility Options: 'hidden', 'visible', 'search' and 'catalog'. */ public function set_catalog_visibility( $visibility ) { $options = array_keys( kkart_get_product_visibility_options() ); if ( ! in_array( $visibility, $options, true ) ) { $this->error( 'product_invalid_catalog_visibility', __( 'Invalid catalog visibility option.', 'kkart' ) ); } $this->set_prop( 'catalog_visibility', $visibility ); } /** * Set product description. * * @since 3.0.0 * @param string $description Product description. */ public function set_description( $description ) { $this->set_prop( 'description', $description ); } /** * Set product short description. * * @since 3.0.0 * @param string $short_description Product short description. */ public function set_short_description( $short_description ) { $this->set_prop( 'short_description', $short_description ); } /** * Set SKU. * * @since 3.0.0 * @throws KKART_Data_Exception Throws exception when invalid data is found. * @param string $sku Product SKU. */ public function set_sku( $sku ) { $sku = (string) $sku; if ( $this->get_object_read() && ! empty( $sku ) && ! kkart_product_has_unique_sku( $this->get_id(), $sku ) ) { $sku_found = kkart_get_product_id_by_sku( $sku ); $this->error( 'product_invalid_sku', __( 'Invalid or duplicated SKU.', 'kkart' ), 400, array( 'resource_id' => $sku_found ) ); } $this->set_prop( 'sku', $sku ); } /** * Set the product's active price. * * @param string $price Price. */ public function set_price( $price ) { $this->set_prop( 'price', kkart_format_decimal( $price ) ); } /** * Set the product's regular price. * * @since 3.0.0 * @param string $price Regular price. */ public function set_regular_price( $price ) { $this->set_prop( 'regular_price', kkart_format_decimal( $price ) ); } /** * Set the product's sale price. * * @since 3.0.0 * @param string $price sale price. */ public function set_sale_price( $price ) { $this->set_prop( 'sale_price', kkart_format_decimal( $price ) ); } /** * Set date on sale from. * * @since 3.0.0 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. */ public function set_date_on_sale_from( $date = null ) { $this->set_date_prop( 'date_on_sale_from', $date ); } /** * Set date on sale to. * * @since 3.0.0 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if their is no date. */ public function set_date_on_sale_to( $date = null ) { $this->set_date_prop( 'date_on_sale_to', $date ); } /** * Set number total of sales. * * @since 3.0.0 * @param int $total Total of sales. */ public function set_total_sales( $total ) { $this->set_prop( 'total_sales', absint( $total ) ); } /** * Set the tax status. * * @since 3.0.0 * @throws KKART_Data_Exception Throws exception when invalid data is found. * @param string $status Tax status. */ public function set_tax_status( $status ) { $options = array( 'taxable', 'shipping', 'none', ); // Set default if empty. if ( empty( $status ) ) { $status = 'taxable'; } if ( ! in_array( $status, $options, true ) ) { $this->error( 'product_invalid_tax_status', __( 'Invalid product tax status.', 'kkart' ) ); } $this->set_prop( 'tax_status', $status ); } /** * Set the tax class. * * @since 3.0.0 * @param string $class Tax class. */ public function set_tax_class( $class ) { $class = sanitize_title( $class ); $class = 'standard' === $class ? '' : $class; $valid_classes = $this->get_valid_tax_classes(); if ( ! in_array( $class, $valid_classes, true ) ) { $class = ''; } $this->set_prop( 'tax_class', $class ); } /** * Return an array of valid tax classes * * @return array valid tax classes */ protected function get_valid_tax_classes() { return KKART_Tax::get_tax_class_slugs(); } /** * Set if product manage stock. * * @since 3.0.0 * @param bool $manage_stock Whether or not manage stock is enabled. */ public function set_manage_stock( $manage_stock ) { $this->set_prop( 'manage_stock', kkart_string_to_bool( $manage_stock ) ); } /** * Set number of items available for sale. * * @since 3.0.0 * @param float|null $quantity Stock quantity. */ public function set_stock_quantity( $quantity ) { $this->set_prop( 'stock_quantity', '' !== $quantity ? kkart_stock_amount( $quantity ) : null ); } /** * Set stock status. * * @param string $status New status. */ public function set_stock_status( $status = 'instock' ) { $valid_statuses = kkart_get_product_stock_status_options(); if ( isset( $valid_statuses[ $status ] ) ) { $this->set_prop( 'stock_status', $status ); } else { $this->set_prop( 'stock_status', 'instock' ); } } /** * Set backorders. * * @since 3.0.0 * @param string $backorders Options: 'yes', 'no' or 'notify'. */ public function set_backorders( $backorders ) { $this->set_prop( 'backorders', $backorders ); } /** * Set low stock amount. * * @param int|string $amount Empty string if value not set. * @since 3.5.0 */ public function set_low_stock_amount( $amount ) { $this->set_prop( 'low_stock_amount', '' === $amount ? '' : absint( $amount ) ); } /** * Set if should be sold individually. * * @since 3.0.0 * @param bool $sold_individually Whether or not product is sold individually. */ public function set_sold_individually( $sold_individually ) { $this->set_prop( 'sold_individually', kkart_string_to_bool( $sold_individually ) ); } /** * Set the product's weight. * * @since 3.0.0 * @param float|string $weight Total weight. */ public function set_weight( $weight ) { $this->set_prop( 'weight', '' === $weight ? '' : kkart_format_decimal( $weight ) ); } /** * Set the product length. * * @since 3.0.0 * @param float|string $length Total length. */ public function set_length( $length ) { $this->set_prop( 'length', '' === $length ? '' : kkart_format_decimal( $length ) ); } /** * Set the product width. * * @since 3.0.0 * @param float|string $width Total width. */ public function set_width( $width ) { $this->set_prop( 'width', '' === $width ? '' : kkart_format_decimal( $width ) ); } /** * Set the product height. * * @since 3.0.0 * @param float|string $height Total height. */ public function set_height( $height ) { $this->set_prop( 'height', '' === $height ? '' : kkart_format_decimal( $height ) ); } /** * Set upsell IDs. * * @since 3.0.0 * @param array $upsell_ids IDs from the up-sell products. */ public function set_upsell_ids( $upsell_ids ) { $this->set_prop( 'upsell_ids', array_filter( (array) $upsell_ids ) ); } /** * Set crosssell IDs. * * @since 3.0.0 * @param array $cross_sell_ids IDs from the cross-sell products. */ public function set_cross_sell_ids( $cross_sell_ids ) { $this->set_prop( 'cross_sell_ids', array_filter( (array) $cross_sell_ids ) ); } /** * Set parent ID. * * @since 3.0.0 * @param int $parent_id Product parent ID. */ public function set_parent_id( $parent_id ) { $this->set_prop( 'parent_id', absint( $parent_id ) ); } /** * Set if reviews is allowed. * * @since 3.0.0 * @param bool $reviews_allowed Reviews allowed or not. */ public function set_reviews_allowed( $reviews_allowed ) { $this->set_prop( 'reviews_allowed', kkart_string_to_bool( $reviews_allowed ) ); } /** * Set purchase note. * * @since 3.0.0 * @param string $purchase_note Purchase note. */ public function set_purchase_note( $purchase_note ) { $this->set_prop( 'purchase_note', $purchase_note ); } /** * Set product attributes. * * Attributes are made up of: * id - 0 for product level attributes. ID for global attributes. * name - Attribute name. * options - attribute value or array of term ids/names. * position - integer sort order. * visible - If visible on frontend. * variation - If used for variations. * Indexed by unqiue key to allow clearing old ones after a set. * * @since 3.0.0 * @param array $raw_attributes Array of KKART_Product_Attribute objects. */ public function set_attributes( $raw_attributes ) { $attributes = array_fill_keys( array_keys( $this->get_attributes( 'edit' ) ), null ); foreach ( $raw_attributes as $attribute ) { if ( is_a( $attribute, 'KKART_Product_Attribute' ) ) { $attributes[ sanitize_title( $attribute->get_name() ) ] = $attribute; } } uasort( $attributes, 'kkart_product_attribute_uasort_comparison' ); $this->set_prop( 'attributes', $attributes ); } /** * Set default attributes. These will be saved as strings and should map to attribute values. * * @since 3.0.0 * @param array $default_attributes List of default attributes. */ public function set_default_attributes( $default_attributes ) { $this->set_prop( 'default_attributes', array_map( 'strval', array_filter( (array) $default_attributes, 'kkart_array_filter_default_attributes' ) ) ); } /** * Set menu order. * * @since 3.0.0 * @param int $menu_order Menu order. */ public function set_menu_order( $menu_order ) { $this->set_prop( 'menu_order', intval( $menu_order ) ); } /** * Set post password. * * @since 3.6.0 * @param int $post_password Post password. */ public function set_post_password( $post_password ) { $this->set_prop( 'post_password', $post_password ); } /** * Set the product categories. * * @since 3.0.0 * @param array $term_ids List of terms IDs. */ public function set_category_ids( $term_ids ) { $this->set_prop( 'category_ids', array_unique( array_map( 'intval', $term_ids ) ) ); } /** * Set the product tags. * * @since 3.0.0 * @param array $term_ids List of terms IDs. */ public function set_tag_ids( $term_ids ) { $this->set_prop( 'tag_ids', array_unique( array_map( 'intval', $term_ids ) ) ); } /** * Set if the product is virtual. * * @since 3.0.0 * @param bool|string $virtual Whether product is virtual or not. */ public function set_virtual( $virtual ) { $this->set_prop( 'virtual', kkart_string_to_bool( $virtual ) ); } /** * Set shipping class ID. * * @since 3.0.0 * @param int $id Product shipping class id. */ public function set_shipping_class_id( $id ) { $this->set_prop( 'shipping_class_id', absint( $id ) ); } /** * Set if the product is downloadable. * * @since 3.0.0 * @param bool|string $downloadable Whether product is downloadable or not. */ public function set_downloadable( $downloadable ) { $this->set_prop( 'downloadable', kkart_string_to_bool( $downloadable ) ); } /** * Set downloads. * * @since 3.0.0 * @param array $downloads_array Array of KKART_Product_Download objects or arrays. */ public function set_downloads( $downloads_array ) { $downloads = array(); $errors = array(); foreach ( $downloads_array as $download ) { if ( is_a( $download, 'KKART_Product_Download' ) ) { $download_object = $download; } else { $download_object = new KKART_Product_Download(); // If we don't have a previous hash, generate UUID for download. if ( empty( $download['download_id'] ) ) { $download['download_id'] = wp_generate_uuid4(); } $download_object->set_id( $download['download_id'] ); $download_object->set_name( $download['name'] ); $download_object->set_file( $download['file'] ); } // Validate the file extension. if ( ! $download_object->is_allowed_filetype() ) { if ( $this->get_object_read() ) { /* translators: %1$s: Downloadable file */ $errors[] = sprintf( __( 'The downloadable file %1$s cannot be used as it does not have an allowed file type. Allowed types include: %2$s', 'kkart' ), '' . basename( $download_object->get_file() ) . '', '' . implode( ', ', array_keys( $download_object->get_allowed_mime_types() ) ) . '' ); } continue; } // Validate the file exists. if ( ! $download_object->file_exists() ) { if ( $this->get_object_read() ) { /* translators: %s: Downloadable file */ $errors[] = sprintf( __( 'The downloadable file %s cannot be used as it does not exist on the server.', 'kkart' ), '' . $download_object->get_file() . '' ); } continue; } $downloads[ $download_object->get_id() ] = $download_object; } if ( $errors ) { $this->error( 'product_invalid_download', $errors[0] ); } $this->set_prop( 'downloads', $downloads ); } /** * Set download limit. * * @since 3.0.0 * @param int|string $download_limit Product download limit. */ public function set_download_limit( $download_limit ) { $this->set_prop( 'download_limit', -1 === (int) $download_limit || '' === $download_limit ? -1 : absint( $download_limit ) ); } /** * Set download expiry. * * @since 3.0.0 * @param int|string $download_expiry Product download expiry. */ public function set_download_expiry( $download_expiry ) { $this->set_prop( 'download_expiry', -1 === (int) $download_expiry || '' === $download_expiry ? -1 : absint( $download_expiry ) ); } /** * Set gallery attachment ids. * * @since 3.0.0 * @param array $image_ids List of image ids. */ public function set_gallery_image_ids( $image_ids ) { $image_ids = wp_parse_id_list( $image_ids ); $this->set_prop( 'gallery_image_ids', $image_ids ); } /** * Set main image ID. * * @since 3.0.0 * @param int|string $image_id Product image id. */ public function set_image_id( $image_id = '' ) { $this->set_prop( 'image_id', $image_id ); } /** * Set rating counts. Read only. * * @param array $counts Product rating counts. */ public function set_rating_counts( $counts ) { $this->set_prop( 'rating_counts', array_filter( array_map( 'absint', (array) $counts ) ) ); } /** * Set average rating. Read only. * * @param float $average Product average rating. */ public function set_average_rating( $average ) { $this->set_prop( 'average_rating', kkart_format_decimal( $average ) ); } /** * Set review count. Read only. * * @param int $count Product review count. */ public function set_review_count( $count ) { $this->set_prop( 'review_count', absint( $count ) ); } /* |-------------------------------------------------------------------------- | Other Methods |-------------------------------------------------------------------------- */ /** * Ensure properties are set correctly before save. * * @since 3.0.0 */ public function validate_props() { // Before updating, ensure stock props are all aligned. Qty, backorders and low stock amount are not needed if not stock managed. if ( ! $this->get_manage_stock() ) { $this->set_stock_quantity( '' ); $this->set_backorders( 'no' ); $this->set_low_stock_amount( '' ); return; } $stock_is_above_notification_threshold = ( $this->get_stock_quantity() > get_option( 'kkart_notify_no_stock_amount', 0 ) ); $backorders_are_allowed = ( 'no' !== $this->get_backorders() ); if ( $stock_is_above_notification_threshold ) { $new_stock_status = 'instock'; } elseif ( $backorders_are_allowed ) { $new_stock_status = 'onbackorder'; } else { $new_stock_status = 'outofstock'; } $this->set_stock_status( $new_stock_status ); } /** * Save data (either create or update depending on if we are working on an existing product). * * @since 3.0.0 * @return int */ public function save() { $this->validate_props(); if ( ! $this->data_store ) { return $this->get_id(); } /** * Trigger action before saving to the DB. Allows you to adjust object props before save. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_before_' . $this->object_type . '_object_save', $this, $this->data_store ); if ( $this->get_id() ) { $this->data_store->update( $this ); } else { $this->data_store->create( $this ); } $this->maybe_defer_product_sync(); /** * Trigger action after saving to the DB. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_after_' . $this->object_type . '_object_save', $this, $this->data_store ); return $this->get_id(); } /** * Delete the product, set its ID to 0, and return result. * * @param bool $force_delete Should the product be deleted permanently. * @return bool result */ public function delete( $force_delete = false ) { $deleted = parent::delete( $force_delete ); if ( $deleted ) { $this->maybe_defer_product_sync(); } return $deleted; } /** * If this is a child product, queue its parent for syncing at the end of the request. */ protected function maybe_defer_product_sync() { $parent_id = $this->get_parent_id(); if ( $parent_id ) { kkart_deferred_product_sync( $parent_id ); } } /* |-------------------------------------------------------------------------- | Conditionals |-------------------------------------------------------------------------- */ /** * Check if a product supports a given feature. * * Product classes should override this to declare support (or lack of support) for a feature. * * @param string $feature string The name of a feature to test support for. * @return bool True if the product supports the feature, false otherwise. * @since 2.5.0 */ public function supports( $feature ) { return apply_filters( 'kkart_product_supports', in_array( $feature, $this->supports, true ), $feature, $this ); } /** * Returns whether or not the product post exists. * * @return bool */ public function exists() { return false !== $this->get_status(); } /** * Checks the product type. * * Backwards compatibility with downloadable/virtual. * * @param string|array $type Array or string of types. * @return bool */ public function is_type( $type ) { return ( $this->get_type() === $type || ( is_array( $type ) && in_array( $this->get_type(), $type, true ) ) ); } /** * Checks if a product is downloadable. * * @return bool */ public function is_downloadable() { return apply_filters( 'kkart_is_downloadable', true === $this->get_downloadable(), $this ); } /** * Checks if a product is virtual (has no shipping). * * @return bool */ public function is_virtual() { return apply_filters( 'kkart_is_virtual', true === $this->get_virtual(), $this ); } /** * Returns whether or not the product is featured. * * @return bool */ public function is_featured() { return true === $this->get_featured(); } /** * Check if a product is sold individually (no quantities). * * @return bool */ public function is_sold_individually() { return apply_filters( 'kkart_is_sold_individually', true === $this->get_sold_individually(), $this ); } /** * Returns whether or not the product is visible in the catalog. * * @return bool */ public function is_visible() { $visible = $this->is_visible_core(); return apply_filters( 'kkart_product_is_visible', $visible, $this->get_id() ); } /** * Returns whether or not the product is visible in the catalog (doesn't trigger filters). * * @return bool */ protected function is_visible_core() { $visible = 'visible' === $this->get_catalog_visibility() || ( is_search() && 'search' === $this->get_catalog_visibility() ) || ( ! is_search() && 'catalog' === $this->get_catalog_visibility() ); if ( 'trash' === $this->get_status() ) { $visible = false; } elseif ( 'publish' !== $this->get_status() && ! current_user_can( 'edit_post', $this->get_id() ) ) { $visible = false; } if ( $this->get_parent_id() ) { $parent_product = kkart_get_product( $this->get_parent_id() ); if ( $parent_product && 'publish' !== $parent_product->get_status() ) { $visible = false; } } if ( 'yes' === get_option( 'kkart_hide_out_of_stock_items' ) && ! $this->is_in_stock() ) { $visible = false; } return $visible; } /** * Returns false if the product cannot be bought. * * @return bool */ public function is_purchasable() { return apply_filters( 'kkart_is_purchasable', $this->exists() && ( 'publish' === $this->get_status() || current_user_can( 'edit_post', $this->get_id() ) ) && '' !== $this->get_price(), $this ); } /** * Returns whether or not the product is on sale. * * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function is_on_sale( $context = 'view' ) { if ( '' !== (string) $this->get_sale_price( $context ) && $this->get_regular_price( $context ) > $this->get_sale_price( $context ) ) { $on_sale = true; if ( $this->get_date_on_sale_from( $context ) && $this->get_date_on_sale_from( $context )->getTimestamp() > time() ) { $on_sale = false; } if ( $this->get_date_on_sale_to( $context ) && $this->get_date_on_sale_to( $context )->getTimestamp() < time() ) { $on_sale = false; } } else { $on_sale = false; } return 'view' === $context ? apply_filters( 'kkart_product_is_on_sale', $on_sale, $this ) : $on_sale; } /** * Returns whether or not the product has dimensions set. * * @return bool */ public function has_dimensions() { return ( $this->get_length() || $this->get_height() || $this->get_width() ) && ! $this->get_virtual(); } /** * Returns whether or not the product has weight set. * * @return bool */ public function has_weight() { return $this->get_weight() && ! $this->get_virtual(); } /** * Returns whether or not the product can be purchased. * This returns true for 'instock' and 'onbackorder' stock statuses. * * @return bool */ public function is_in_stock() { return apply_filters( 'kkart_product_is_in_stock', 'outofstock' !== $this->get_stock_status(), $this ); } /** * Checks if a product needs shipping. * * @return bool */ public function needs_shipping() { return apply_filters( 'kkart_product_needs_shipping', ! $this->is_virtual(), $this ); } /** * Returns whether or not the product is taxable. * * @return bool */ public function is_taxable() { return apply_filters( 'kkart_product_is_taxable', $this->get_tax_status() === 'taxable' && kkart_tax_enabled(), $this ); } /** * Returns whether or not the product shipping is taxable. * * @return bool */ public function is_shipping_taxable() { return $this->needs_shipping() && ( $this->get_tax_status() === 'taxable' || $this->get_tax_status() === 'shipping' ); } /** * Returns whether or not the product is stock managed. * * @return bool */ public function managing_stock() { if ( 'yes' === get_option( 'kkart_manage_stock' ) ) { return $this->get_manage_stock(); } return false; } /** * Returns whether or not the product can be backordered. * * @return bool */ public function backorders_allowed() { return apply_filters( 'kkart_product_backorders_allowed', ( 'yes' === $this->get_backorders() || 'notify' === $this->get_backorders() ), $this->get_id(), $this ); } /** * Returns whether or not the product needs to notify the customer on backorder. * * @return bool */ public function backorders_require_notification() { return apply_filters( 'kkart_product_backorders_require_notification', ( $this->managing_stock() && 'notify' === $this->get_backorders() ), $this ); } /** * Check if a product is on backorder. * * @param int $qty_in_cart (default: 0). * @return bool */ public function is_on_backorder( $qty_in_cart = 0 ) { if ( 'onbackorder' === $this->get_stock_status() ) { return true; } return $this->managing_stock() && $this->backorders_allowed() && ( $this->get_stock_quantity() - $qty_in_cart ) < 0; } /** * Returns whether or not the product has enough stock for the order. * * @param mixed $quantity Quantity of a product added to an order. * @return bool */ public function has_enough_stock( $quantity ) { return ! $this->managing_stock() || $this->backorders_allowed() || $this->get_stock_quantity() >= $quantity; } /** * Returns whether or not the product has any visible attributes. * * @return boolean */ public function has_attributes() { foreach ( $this->get_attributes() as $attribute ) { if ( $attribute->get_visible() ) { return true; } } return false; } /** * Returns whether or not the product has any child product. * * @return bool */ public function has_child() { return 0 < count( $this->get_children() ); } /** * Does a child have dimensions? * * @since 3.0.0 * @return bool */ public function child_has_dimensions() { return false; } /** * Does a child have a weight? * * @since 3.0.0 * @return boolean */ public function child_has_weight() { return false; } /** * Check if downloadable product has a file attached. * * @since 1.6.2 * * @param string $download_id file identifier. * @return bool Whether downloadable product has a file attached. */ public function has_file( $download_id = '' ) { return $this->is_downloadable() && $this->get_file( $download_id ); } /** * Returns whether or not the product has additional options that need * selecting before adding to cart. * * @since 3.0.0 * @return boolean */ public function has_options() { return apply_filters( 'kkart_product_has_options', false, $this ); } /* |-------------------------------------------------------------------------- | Non-CRUD Getters |-------------------------------------------------------------------------- */ /** * Get the product's title. For products this is the product name. * * @return string */ public function get_title() { return apply_filters( 'kkart_product_title', $this->get_name(), $this ); } /** * Product permalink. * * @return string */ public function get_permalink() { return get_permalink( $this->get_id() ); } /** * Returns the children IDs if applicable. Overridden by child classes. * * @return array of IDs */ public function get_children() { return array(); } /** * If the stock level comes from another product ID, this should be modified. * * @since 3.0.0 * @return int */ public function get_stock_managed_by_id() { return $this->get_id(); } /** * Returns the price in html format. * * @param string $deprecated Deprecated param. * * @return string */ public function get_price_html( $deprecated = '' ) { if ( '' === $this->get_price() ) { $price = apply_filters( 'kkart_empty_price_html', '', $this ); } elseif ( $this->is_on_sale() ) { $price = kkart_format_sale_price( kkart_get_price_to_display( $this, array( 'price' => $this->get_regular_price() ) ), kkart_get_price_to_display( $this ) ) . $this->get_price_suffix(); } else { $price = kkart_price( kkart_get_price_to_display( $this ) ) . $this->get_price_suffix(); } return apply_filters( 'kkart_get_price_html', $price, $this ); } /** * Get product name with SKU or ID. Used within admin. * * @return string Formatted product name */ public function get_formatted_name() { if ( $this->get_sku() ) { $identifier = $this->get_sku(); } else { $identifier = '#' . $this->get_id(); } return sprintf( '%2$s (%1$s)', $identifier, $this->get_name() ); } /** * Get min quantity which can be purchased at once. * * @since 3.0.0 * @return int */ public function get_min_purchase_quantity() { return 1; } /** * Get max quantity which can be purchased at once. * * @since 3.0.0 * @return int Quantity or -1 if unlimited. */ public function get_max_purchase_quantity() { return $this->is_sold_individually() ? 1 : ( $this->backorders_allowed() || ! $this->managing_stock() ? -1 : $this->get_stock_quantity() ); } /** * Get the add to url used mainly in loops. * * @return string */ public function add_to_cart_url() { return apply_filters( 'kkart_product_add_to_cart_url', $this->get_permalink(), $this ); } /** * Get the add to cart button text for the single page. * * @return string */ public function single_add_to_cart_text() { return apply_filters( 'kkart_product_single_add_to_cart_text', __( 'Add to cart', 'kkart' ), $this ); } /** * Get the add to cart button text. * * @return string */ public function add_to_cart_text() { return apply_filters( 'kkart_product_add_to_cart_text', __( 'Read more', 'kkart' ), $this ); } /** * Get the add to cart button text description - used in aria tags. * * @since 3.3.0 * @return string */ public function add_to_cart_description() { /* translators: %s: Product title */ return apply_filters( 'kkart_product_add_to_cart_description', sprintf( __( 'Read more about “%s”', 'kkart' ), $this->get_name() ), $this ); } /** * Returns the main product image. * * @param string $size (default: 'kkart_thumbnail'). * @param array $attr Image attributes. * @param bool $placeholder True to return $placeholder if no image is found, or false to return an empty string. * @return string */ public function get_image( $size = 'kkart_thumbnail', $attr = array(), $placeholder = true ) { $image = ''; if ( $this->get_image_id() ) { $image = wp_get_attachment_image( $this->get_image_id(), $size, false, $attr ); } elseif ( $this->get_parent_id() ) { $parent_product = kkart_get_product( $this->get_parent_id() ); if ( $parent_product ) { $image = $parent_product->get_image( $size, $attr, $placeholder ); } } if ( ! $image && $placeholder ) { $image = kkart_placeholder_img( $size, $attr ); } return apply_filters( 'kkart_product_get_image', $image, $this, $size, $attr, $placeholder, $image ); } /** * Returns the product shipping class SLUG. * * @return string */ public function get_shipping_class() { $class_id = $this->get_shipping_class_id(); if ( $class_id ) { $term = get_term_by( 'id', $class_id, 'product_shipping_class' ); if ( $term && ! is_wp_error( $term ) ) { return $term->slug; } } return ''; } /** * Returns a single product attribute as a string. * * @param string $attribute to get. * @return string */ public function get_attribute( $attribute ) { $attributes = $this->get_attributes(); $attribute = sanitize_title( $attribute ); if ( isset( $attributes[ $attribute ] ) ) { $attribute_object = $attributes[ $attribute ]; } elseif ( isset( $attributes[ 'pa_' . $attribute ] ) ) { $attribute_object = $attributes[ 'pa_' . $attribute ]; } else { return ''; } return $attribute_object->is_taxonomy() ? implode( ', ', kkart_get_product_terms( $this->get_id(), $attribute_object->get_name(), array( 'fields' => 'names' ) ) ) : kkart_implode_text_attributes( $attribute_object->get_options() ); } /** * Get the total amount (COUNT) of ratings, or just the count for one rating e.g. number of 5 star ratings. * * @param int $value Optional. Rating value to get the count for. By default returns the count of all rating values. * @return int */ public function get_rating_count( $value = null ) { $counts = $this->get_rating_counts(); if ( is_null( $value ) ) { return array_sum( $counts ); } elseif ( isset( $counts[ $value ] ) ) { return absint( $counts[ $value ] ); } else { return 0; } } /** * Get a file by $download_id. * * @param string $download_id file identifier. * @return array|false if not found */ public function get_file( $download_id = '' ) { $files = $this->get_downloads(); if ( '' === $download_id ) { $file = count( $files ) ? current( $files ) : false; } elseif ( isset( $files[ $download_id ] ) ) { $file = $files[ $download_id ]; } else { $file = false; } return apply_filters( 'kkart_product_file', $file, $this, $download_id ); } /** * Get file download path identified by $download_id. * * @param string $download_id file identifier. * @return string */ public function get_file_download_path( $download_id ) { $files = $this->get_downloads(); $file_path = isset( $files[ $download_id ] ) ? $files[ $download_id ]->get_file() : ''; // allow overriding based on the particular file being requested. return apply_filters( 'kkart_product_file_download_path', $file_path, $this, $download_id ); } /** * Get the suffix to display after prices > 0. * * @param string $price to calculate, left blank to just use get_price(). * @param integer $qty passed on to get_price_including_tax() or get_price_excluding_tax(). * @return string */ public function get_price_suffix( $price = '', $qty = 1 ) { $html = ''; $suffix = get_option( 'kkart_price_display_suffix' ); if ( $suffix && kkart_tax_enabled() && 'taxable' === $this->get_tax_status() ) { if ( '' === $price ) { $price = $this->get_price(); } $replacements = array( '{price_including_tax}' => kkart_price( kkart_get_price_including_tax( $this, array( 'qty' => $qty, 'price' => $price ) ) ), // @phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.ArrayItemNoNewLine, WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound '{price_excluding_tax}' => kkart_price( kkart_get_price_excluding_tax( $this, array( 'qty' => $qty, 'price' => $price ) ) ), // @phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound ); $html = str_replace( array_keys( $replacements ), array_values( $replacements ), ' ' . wp_kses_post( $suffix ) . '' ); } return apply_filters( 'kkart_get_price_suffix', $html, $this, $price, $qty ); } /** * Returns the availability of the product. * * @return string[] */ public function get_availability() { return apply_filters( 'kkart_get_availability', array( 'availability' => $this->get_availability_text(), 'class' => $this->get_availability_class(), ), $this ); } /** * Get availability text based on stock status. * * @return string */ protected function get_availability_text() { if ( ! $this->is_in_stock() ) { $availability = __( 'Out of stock', 'kkart' ); } elseif ( $this->managing_stock() && $this->is_on_backorder( 1 ) ) { $availability = $this->backorders_require_notification() ? __( 'Available on backorder', 'kkart' ) : ''; } elseif ( ! $this->managing_stock() && $this->is_on_backorder( 1 ) ) { $availability = __( 'Available on backorder', 'kkart' ); } elseif ( $this->managing_stock() ) { $availability = kkart_format_stock_for_display( $this ); } else { $availability = ''; } return apply_filters( 'kkart_get_availability_text', $availability, $this ); } /** * Get availability classname based on stock status. * * @return string */ protected function get_availability_class() { if ( ! $this->is_in_stock() ) { $class = 'out-of-stock'; } elseif ( ( $this->managing_stock() && $this->is_on_backorder( 1 ) ) || ( ! $this->managing_stock() && $this->is_on_backorder( 1 ) ) ) { $class = 'available-on-backorder'; } else { $class = 'in-stock'; } return apply_filters( 'kkart_get_availability_class', $class, $this ); } } PK!u*)abstracts/abstract-kkart-object-query.phpnu[query_vars = wp_parse_args( $args, $this->get_default_query_vars() ); } /** * Get the current query vars. * * @return array */ public function get_query_vars() { return $this->query_vars; } /** * Get the value of a query variable. * * @param string $query_var Query variable to get value for. * @param mixed $default Default value if query variable is not set. * @return mixed Query variable value if set, otherwise default. */ public function get( $query_var, $default = '' ) { if ( isset( $this->query_vars[ $query_var ] ) ) { return $this->query_vars[ $query_var ]; } return $default; } /** * Set a query variable. * * @param string $query_var Query variable to set. * @param mixed $value Value to set for query variable. */ public function set( $query_var, $value ) { $this->query_vars[ $query_var ] = $value; } /** * Get the default allowed query vars. * * @return array */ protected function get_default_query_vars() { return array( 'name' => '', 'parent' => '', 'parent_exclude' => '', 'exclude' => '', 'limit' => get_option( 'posts_per_page' ), 'page' => 1, 'offset' => '', 'paginate' => false, 'order' => 'DESC', 'orderby' => 'date', 'return' => 'objects', ); } } PK!oC*abstracts/abstract-kkart-payment-token.phpnu[ '', 'token' => '', 'is_default' => false, 'user_id' => 0, 'type' => '', ); /** * Token Type (CC, eCheck, or a custom type added by an extension). * Set by child classes. * * @var string */ protected $type = ''; /** * Initialize a payment token. * * These fields are accepted by all payment tokens: * is_default - boolean Optional - Indicates this is the default payment token for a user * token - string Required - The actual token to store * gateway_id - string Required - Identifier for the gateway this token is associated with * user_id - int Optional - ID for the user this token is associated with. 0 if this token is not associated with a user * * @since 2.6.0 * @param mixed $token Token. */ public function __construct( $token = '' ) { parent::__construct( $token ); if ( is_numeric( $token ) ) { $this->set_id( $token ); } elseif ( is_object( $token ) ) { $token_id = $token->get_id(); if ( ! empty( $token_id ) ) { $this->set_id( $token->get_id() ); } } else { $this->set_object_read( true ); } $this->data_store = KKART_Data_Store::load( 'payment-token' ); if ( $this->get_id() > 0 ) { $this->data_store->read( $this ); } } /* *-------------------------------------------------------------------------- * Getters *-------------------------------------------------------------------------- */ /** * Returns the raw payment token. * * @since 2.6.0 * @param string $context Context in which to call this. * @return string Raw token */ public function get_token( $context = 'view' ) { return $this->get_prop( 'token', $context ); } /** * Returns the type of this payment token (CC, eCheck, or something else). * Overwritten by child classes. * * @since 2.6.0 * @param string $deprecated Deprecated since Kkart 3.0. * @return string Payment Token Type (CC, eCheck) */ public function get_type( $deprecated = '' ) { return $this->type; } /** * Get type to display to user. * Get's overwritten by child classes. * * @since 2.6.0 * @param string $deprecated Deprecated since Kkart 3.0. * @return string */ public function get_display_name( $deprecated = '' ) { return $this->get_type(); } /** * Returns the user ID associated with the token or false if this token is not associated. * * @since 2.6.0 * @param string $context In what context to execute this. * @return int User ID if this token is associated with a user or 0 if no user is associated */ public function get_user_id( $context = 'view' ) { return $this->get_prop( 'user_id', $context ); } /** * Returns the ID of the gateway associated with this payment token. * * @since 2.6.0 * @param string $context In what context to execute this. * @return string Gateway ID */ public function get_gateway_id( $context = 'view' ) { return $this->get_prop( 'gateway_id', $context ); } /** * Returns the ID of the gateway associated with this payment token. * * @since 2.6.0 * @param string $context In what context to execute this. * @return string Gateway ID */ public function get_is_default( $context = 'view' ) { return $this->get_prop( 'is_default', $context ); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- */ /** * Set the raw payment token. * * @since 2.6.0 * @param string $token Payment token. */ public function set_token( $token ) { $this->set_prop( 'token', $token ); } /** * Set the user ID for the user associated with this order. * * @since 2.6.0 * @param int $user_id User ID. */ public function set_user_id( $user_id ) { $this->set_prop( 'user_id', absint( $user_id ) ); } /** * Set the gateway ID. * * @since 2.6.0 * @param string $gateway_id Gateway ID. */ public function set_gateway_id( $gateway_id ) { $this->set_prop( 'gateway_id', $gateway_id ); } /** * Marks the payment as default or non-default. * * @since 2.6.0 * @param boolean $is_default True or false. */ public function set_default( $is_default ) { $this->set_prop( 'is_default', (bool) $is_default ); } /* |-------------------------------------------------------------------------- | Other Methods |-------------------------------------------------------------------------- */ /** * Returns if the token is marked as default. * * @since 2.6.0 * @return boolean True if the token is default */ public function is_default() { return (bool) $this->get_prop( 'is_default', 'view' ); } /** * Validate basic token info (token and type are required). * * @since 2.6.0 * @return boolean True if the passed data is valid */ public function validate() { $token = $this->get_prop( 'token', 'edit' ); if ( empty( $token ) ) { return false; } return true; } } PK!1TT(abstracts/abstract-kkart-integration.phpnu[method_title, $this ); } /** * Return the description for admin screens. * * @return string */ public function get_method_description() { return apply_filters( 'kkart_integration_description', $this->method_description, $this ); } /** * Output the gateway settings screen. */ public function admin_options() { echo '

' . esc_html( $this->get_method_title() ) . '

'; echo wp_kses_post( wpautop( $this->get_method_description() ) ); echo '
'; parent::admin_options(); } /** * Init settings for gateways. */ public function init_settings() { parent::init_settings(); $this->enabled = ! empty( $this->settings['enabled'] ) && 'yes' === $this->settings['enabled'] ? 'yes' : 'no'; } } PK!. ? ?,abstracts/abstract-kkart-shipping-method.phpnu[instance_id = absint( $instance_id ); } /** * Check if a shipping method supports a given feature. * * Methods should override this to declare support (or lack of support) for a feature. * * @param string $feature The name of a feature to test support for. * @return bool True if the shipping method supports the feature, false otherwise. */ public function supports( $feature ) { return apply_filters( 'kkart_shipping_method_supports', in_array( $feature, $this->supports ), $feature, $this ); } /** * Called to calculate shipping rates for this method. Rates can be added using the add_rate() method. * * @param array $package Package array. */ public function calculate_shipping( $package = array() ) {} /** * Whether or not we need to calculate tax on top of the shipping rate. * * @return boolean */ public function is_taxable() { return kkart_tax_enabled() && 'taxable' === $this->tax_status && ( KKART()->customer && ! KKART()->customer->get_is_vat_exempt() ); } /** * Whether or not this method is enabled in settings. * * @since 2.6.0 * @return boolean */ public function is_enabled() { return 'yes' === $this->enabled; } /** * Return the shipping method instance ID. * * @since 2.6.0 * @return int */ public function get_instance_id() { return $this->instance_id; } /** * Return the shipping method title. * * @since 2.6.0 * @return string */ public function get_method_title() { return apply_filters( 'kkart_shipping_method_title', $this->method_title, $this ); } /** * Return the shipping method description. * * @since 2.6.0 * @return string */ public function get_method_description() { return apply_filters( 'kkart_shipping_method_description', $this->method_description, $this ); } /** * Return the shipping title which is user set. * * @return string */ public function get_title() { return apply_filters( 'kkart_shipping_method_title', $this->title, $this->id ); } /** * Return calculated rates for a package. * * @since 2.6.0 * @param array $package Package array. * @return array */ public function get_rates_for_package( $package ) { $this->rates = array(); if ( $this->is_available( $package ) && ( empty( $package['ship_via'] ) || in_array( $this->id, $package['ship_via'] ) ) ) { $this->calculate_shipping( $package ); } return $this->rates; } /** * Returns a rate ID based on this methods ID and instance, with an optional * suffix if distinguishing between multiple rates. * * @since 2.6.0 * @param string $suffix Suffix. * @return string */ public function get_rate_id( $suffix = '' ) { $rate_id = array( $this->id ); if ( $this->instance_id ) { $rate_id[] = $this->instance_id; } if ( $suffix ) { $rate_id[] = $suffix; } return implode( ':', $rate_id ); } /** * Add a shipping rate. If taxes are not set they will be calculated based on cost. * * @param array $args Arguments (default: array()). */ public function add_rate( $args = array() ) { $args = apply_filters( 'kkart_shipping_method_add_rate_args', wp_parse_args( $args, array( 'id' => $this->get_rate_id(), // ID for the rate. If not passed, this id:instance default will be used. 'label' => '', // Label for the rate. 'cost' => '0', // Amount or array of costs (per item shipping). 'taxes' => '', // Pass taxes, or leave empty to have it calculated for you, or 'false' to disable calculations. 'calc_tax' => 'per_order', // Calc tax per_order or per_item. Per item needs an array of costs. 'meta_data' => array(), // Array of misc meta data to store along with this rate - key value pairs. 'package' => false, // Package array this rate was generated for @since 2.6.0. 'price_decimals' => kkart_get_price_decimals(), ) ), $this ); // ID and label are required. if ( ! $args['id'] || ! $args['label'] ) { return; } // Total up the cost. $total_cost = is_array( $args['cost'] ) ? array_sum( $args['cost'] ) : $args['cost']; $taxes = $args['taxes']; // Taxes - if not an array and not set to false, calc tax based on cost and passed calc_tax variable. This saves shipping methods having to do complex tax calculations. if ( ! is_array( $taxes ) && false !== $taxes && $total_cost > 0 && $this->is_taxable() ) { $taxes = 'per_item' === $args['calc_tax'] ? $this->get_taxes_per_item( $args['cost'] ) : KKART_Tax::calc_shipping_tax( $total_cost, KKART_Tax::get_shipping_tax_rates() ); } // Round the total cost after taxes have been calculated. $total_cost = kkart_format_decimal( $total_cost, $args['price_decimals'] ); // Create rate object. $rate = new KKART_Shipping_Rate(); $rate->set_id( $args['id'] ); $rate->set_method_id( $this->id ); $rate->set_instance_id( $this->instance_id ); $rate->set_label( $args['label'] ); $rate->set_cost( $total_cost ); $rate->set_taxes( $taxes ); if ( ! empty( $args['meta_data'] ) ) { foreach ( $args['meta_data'] as $key => $value ) { $rate->add_meta_data( $key, $value ); } } // Store package data. if ( $args['package'] ) { $items_in_package = array(); foreach ( $args['package']['contents'] as $item ) { $product = $item['data']; $items_in_package[] = $product->get_name() . ' × ' . $item['quantity']; } $rate->add_meta_data( __( 'Items', 'kkart' ), implode( ', ', $items_in_package ) ); } $this->rates[ $args['id'] ] = apply_filters( 'kkart_shipping_method_add_rate', $rate, $args, $this ); } /** * Calc taxes per item being shipping in costs array. * * @since 2.6.0 * @param array $costs Costs. * @return array of taxes */ protected function get_taxes_per_item( $costs ) { $taxes = array(); // If we have an array of costs we can look up each items tax class and add tax accordingly. if ( is_array( $costs ) ) { $cart = KKART()->cart->get_cart(); foreach ( $costs as $cost_key => $amount ) { if ( ! isset( $cart[ $cost_key ] ) ) { continue; } $item_taxes = KKART_Tax::calc_shipping_tax( $amount, KKART_Tax::get_shipping_tax_rates( $cart[ $cost_key ]['data']->get_tax_class() ) ); // Sum the item taxes. foreach ( array_keys( $taxes + $item_taxes ) as $key ) { $taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 ); } } // Add any cost for the order - order costs are in the key 'order'. if ( isset( $costs['order'] ) ) { $item_taxes = KKART_Tax::calc_shipping_tax( $costs['order'], KKART_Tax::get_shipping_tax_rates() ); // Sum the item taxes. foreach ( array_keys( $taxes + $item_taxes ) as $key ) { $taxes[ $key ] = ( isset( $item_taxes[ $key ] ) ? $item_taxes[ $key ] : 0 ) + ( isset( $taxes[ $key ] ) ? $taxes[ $key ] : 0 ); } } } return $taxes; } /** * Is this method available? * * @param array $package Package. * @return bool */ public function is_available( $package ) { $available = $this->is_enabled(); // Country availability (legacy, for non-zone based methods). if ( ! $this->instance_id && $available ) { $countries = is_array( $this->countries ) ? $this->countries : array(); switch ( $this->availability ) { case 'specific': case 'including': $available = in_array( $package['destination']['country'], array_intersect( $countries, array_keys( KKART()->countries->get_shipping_countries() ) ) ); break; case 'excluding': $available = in_array( $package['destination']['country'], array_diff( array_keys( KKART()->countries->get_shipping_countries() ), $countries ) ); break; default: $available = in_array( $package['destination']['country'], array_keys( KKART()->countries->get_shipping_countries() ) ); break; } } return apply_filters( 'kkart_shipping_' . $this->id . '_is_available', $available, $package, $this ); } /** * Get fee to add to shipping cost. * * @param string|float $fee Fee. * @param float $total Total. * @return float */ public function get_fee( $fee, $total ) { if ( strstr( $fee, '%' ) ) { $fee = ( $total / 100 ) * str_replace( '%', '', $fee ); } if ( ! empty( $this->minimum_fee ) && $this->minimum_fee > $fee ) { $fee = $this->minimum_fee; } return $fee; } /** * Does this method have a settings page? * * @return bool */ public function has_settings() { return $this->instance_id ? $this->supports( 'instance-settings' ) : $this->supports( 'settings' ); } /** * Return admin options as a html string. * * @return string */ public function get_admin_options_html() { if ( $this->instance_id ) { $settings_html = $this->generate_settings_html( $this->get_instance_form_fields(), false ); } else { $settings_html = $this->generate_settings_html( $this->get_form_fields(), false ); } return '' . $settings_html . '
'; } /** * Output the shipping settings screen. */ public function admin_options() { if ( ! $this->instance_id ) { echo '

' . esc_html( $this->get_method_title() ) . '

'; } echo wp_kses_post( wpautop( $this->get_method_description() ) ); echo $this->get_admin_options_html(); // phpcs:ignore WordPress.XSS.EscapeOutput.OutputNotEscaped } /** * Get_option function. * * Gets and option from the settings API, using defaults if necessary to prevent undefined notices. * * @param string $key Key. * @param mixed $empty_value Empty value. * @return mixed The value specified for the option or a default value for the option. */ public function get_option( $key, $empty_value = null ) { // Instance options take priority over global options. if ( $this->instance_id && array_key_exists( $key, $this->get_instance_form_fields() ) ) { return $this->get_instance_option( $key, $empty_value ); } // Return global option. $option = apply_filters( 'kkart_shipping_' . $this->id . '_option', parent::get_option( $key, $empty_value ), $key, $this ); return $option; } /** * Gets an option from the settings API, using defaults if necessary to prevent undefined notices. * * @param string $key Key. * @param mixed $empty_value Empty value. * @return mixed The value specified for the option or a default value for the option. */ public function get_instance_option( $key, $empty_value = null ) { if ( empty( $this->instance_settings ) ) { $this->init_instance_settings(); } // Get option default if unset. if ( ! isset( $this->instance_settings[ $key ] ) ) { $form_fields = $this->get_instance_form_fields(); $this->instance_settings[ $key ] = $this->get_field_default( $form_fields[ $key ] ); } if ( ! is_null( $empty_value ) && '' === $this->instance_settings[ $key ] ) { $this->instance_settings[ $key ] = $empty_value; } $instance_option = apply_filters( 'kkart_shipping_' . $this->id . '_instance_option', $this->instance_settings[ $key ], $key, $this ); return $instance_option; } /** * Get settings fields for instances of this shipping method (within zones). * Should be overridden by shipping methods to add options. * * @since 2.6.0 * @return array */ public function get_instance_form_fields() { return apply_filters( 'kkart_shipping_instance_form_fields_' . $this->id, array_map( array( $this, 'set_defaults' ), $this->instance_form_fields ) ); } /** * Return the name of the option in the WP DB. * * @since 2.6.0 * @return string */ public function get_instance_option_key() { return $this->instance_id ? $this->plugin_id . $this->id . '_' . $this->instance_id . '_settings' : ''; } /** * Initialise Settings for instances. * * @since 2.6.0 */ public function init_instance_settings() { $this->instance_settings = get_option( $this->get_instance_option_key(), null ); // If there are no settings defined, use defaults. if ( ! is_array( $this->instance_settings ) ) { $form_fields = $this->get_instance_form_fields(); $this->instance_settings = array_merge( array_fill_keys( array_keys( $form_fields ), '' ), wp_list_pluck( $form_fields, 'default' ) ); } } /** * Processes and saves global shipping method options in the admin area. * * This method is usually attached to kkart_update_options_x hooks. * * @since 2.6.0 * @return bool was anything saved? */ public function process_admin_options() { if ( ! $this->instance_id ) { return parent::process_admin_options(); } // Check we are processing the correct form for this instance. if ( ! isset( $_REQUEST['instance_id'] ) || absint( $_REQUEST['instance_id'] ) !== $this->instance_id ) { // WPCS: input var ok, CSRF ok. return false; } $this->init_instance_settings(); $post_data = $this->get_post_data(); foreach ( $this->get_instance_form_fields() as $key => $field ) { if ( 'title' !== $this->get_field_type( $field ) ) { try { $this->instance_settings[ $key ] = $this->get_field_value( $key, $field, $post_data ); } catch ( Exception $e ) { $this->add_error( $e->getMessage() ); } } } return update_option( $this->get_instance_option_key(), apply_filters( 'kkart_shipping_' . $this->id . '_instance_settings_values', $this->instance_settings, $this ), 'yes' ); } } PK!rV77,abstracts/abstract-kkart-payment-gateway.phpnu[tokens ) > 0 ) { return $this->tokens; } if ( is_user_logged_in() && $this->supports( 'tokenization' ) ) { $this->tokens = KKART_Payment_Tokens::get_customer_tokens( get_current_user_id(), $this->id ); } return $this->tokens; } /** * Return the title for admin screens. * * @return string */ public function get_method_title() { return apply_filters( 'kkart_gateway_method_title', $this->method_title, $this ); } /** * Return the description for admin screens. * * @return string */ public function get_method_description() { return apply_filters( 'kkart_gateway_method_description', $this->method_description, $this ); } /** * Output the gateway settings screen. */ public function admin_options() { echo '

' . esc_html( $this->get_method_title() ); kkart_back_link( __( 'Return to payments', 'kkart' ), admin_url( 'admin.php?page=kkart-settings&tab=checkout' ) ); echo '

'; echo wp_kses_post( wpautop( $this->get_method_description() ) ); parent::admin_options(); } /** * Init settings for gateways. */ public function init_settings() { parent::init_settings(); $this->enabled = ! empty( $this->settings['enabled'] ) && 'yes' === $this->settings['enabled'] ? 'yes' : 'no'; } /** * Return whether or not this gateway still requires setup to function. * * When this gateway is toggled on via AJAX, if this returns true a * redirect will occur to the settings page instead. * * @since 3.4.0 * @return bool */ public function needs_setup() { return false; } /** * Get the return url (thank you page). * * @param KKART_Order $order Order object. * @return string */ public function get_return_url( $order = null ) { if ( $order ) { $return_url = $order->get_checkout_order_received_url(); } else { $return_url = kkart_get_page_permalink( 'order_received' ); } return apply_filters( 'kkart_get_return_url', $return_url, $order ); } /** * Get a link to the transaction on the 3rd party gateway site (if applicable). * * @param KKART_Order $order the order object. * @return string transaction URL, or empty string. */ public function get_transaction_url( $order ) { $return_url = ''; $transaction_id = $order->get_transaction_id(); if ( ! empty( $this->view_transaction_url ) && ! empty( $transaction_id ) ) { $return_url = sprintf( $this->view_transaction_url, $transaction_id ); } return apply_filters( 'kkart_get_transaction_url', $return_url, $order, $this ); } /** * Get the order total in checkout and pay_for_order. * * @return float */ protected function get_order_total() { $total = 0; $order_id = absint( isset($_GET['order_id'])? $_GET['order_id'] : 0 ); // Gets order total from "pay for order" page. if ( 0 < $order_id ) { $order = kkart_get_order( $order_id ); $total = (float) $order->get_total(); // Gets order total from cart/checkout. } elseif ( 0 < KKART()->cart->total ) { $total = (float) KKART()->cart->total; } return $total; } /** * Check if the gateway is available for use. * * @return bool */ public function is_available() { $is_available = ( 'yes' === $this->enabled ); if ( KKART()->cart && 0 < $this->get_order_total() && 0 < $this->max_amount && $this->max_amount < $this->get_order_total() ) { $is_available = false; } return $is_available; } /** * Check if the gateway has fields on the checkout. * * @return bool */ public function has_fields() { return (bool) $this->has_fields; } /** * Return the gateway's title. * * @return string */ public function get_title() { return apply_filters( 'kkart_gateway_title', $this->title, $this->id ); } /** * Return the gateway's description. * * @return string */ public function get_description() { return apply_filters( 'kkart_gateway_description', $this->description, $this->id ); } /** * Return the gateway's icon. * * @return string */ public function get_icon() { $icon = $this->icon ? '' . esc_attr( $this->get_title() ) . '' : ''; return apply_filters( 'kkart_gateway_icon', $icon, $this->id ); } /** * Return the gateway's pay button ID. * * @since 3.9.0 * @return string */ public function get_pay_button_id() { return sanitize_html_class( $this->pay_button_id ); } /** * Set as current gateway. * * Set this as the current gateway. */ public function set_current() { $this->chosen = true; } /** * Process Payment. * * Process the payment. Override this in your gateway. When implemented, this should. * return the success and redirect in an array. e.g: * * return array( * 'result' => 'success', * 'redirect' => $this->get_return_url( $order ) * ); * * @param int $order_id Order ID. * @return array */ public function process_payment( $order_id ) { return array(); } /** * Process refund. * * If the gateway declares 'refunds' support, this will allow it to refund. * a passed in amount. * * @param int $order_id Order ID. * @param float $amount Refund amount. * @param string $reason Refund reason. * @return boolean True or false based on success, or a WP_Error object. */ public function process_refund( $order_id, $amount = null, $reason = '' ) { return false; } /** * Validate frontend fields. * * Validate payment fields on the frontend. * * @return bool */ public function validate_fields() { return true; } /** * If There are no payment fields show the description if set. * Override this in your gateway if you have some. */ public function payment_fields() { $description = $this->get_description(); if ( $description ) { echo wpautop( wptexturize( $description ) ); // @codingStandardsIgnoreLine. } if ( $this->supports( 'default_credit_card_form' ) ) { $this->credit_card_form(); // Deprecated, will be removed in a future version. } } /** * Check if a gateway supports a given feature. * * Gateways should override this to declare support (or lack of support) for a feature. * For backward compatibility, gateways support 'products' by default, but nothing else. * * @param string $feature string The name of a feature to test support for. * @return bool True if the gateway supports the feature, false otherwise. * @since 1.5.7 */ public function supports( $feature ) { return apply_filters( 'kkart_payment_gateway_supports', in_array( $feature, $this->supports ), $feature, $this ); } /** * Can the order be refunded via this gateway? * * Should be extended by gateways to do their own checks. * * @param KKART_Order $order Order object. * @return bool If false, the automatic refund button is hidden in the UI. */ public function can_refund_order( $order ) { return $order && $this->supports( 'refunds' ); } /** * Core credit card form which gateways can use if needed. Deprecated - inherit KKART_Payment_Gateway_CC instead. * * @param array $args Arguments. * @param array $fields Fields. */ public function credit_card_form( $args = array(), $fields = array() ) { kkart_deprecated_function( 'credit_card_form', '2.6', 'KKART_Payment_Gateway_CC->form' ); $cc_form = new KKART_Payment_Gateway_CC(); $cc_form->id = $this->id; $cc_form->supports = $this->supports; $cc_form->form(); } /** * Enqueues our tokenization script to handle some of the new form options. * * @since 2.6.0 */ public function tokenization_script() { wp_enqueue_script( 'kkart-tokenization-form', plugins_url( '/assets/js/frontend/tokenization-form' . ( Constants::is_true( 'SCRIPT_DEBUG' ) ? '' : '.min' ) . '.js', KKART_PLUGIN_FILE ), array( 'jquery' ), KKART()->version ); wp_localize_script( 'kkart-tokenization-form', 'kkart_tokenization_form_params', array( 'is_registration_required' => KKART()->checkout()->is_registration_required(), 'is_logged_in' => is_user_logged_in(), ) ); } /** * Grab and display our saved payment methods. * * @since 2.6.0 */ public function saved_payment_methods() { $html = '
    '; foreach ( $this->get_tokens() as $token ) { $html .= $this->get_saved_payment_method_option_html( $token ); } $html .= $this->get_new_payment_method_option_html(); $html .= '
'; echo apply_filters( 'kkart_payment_gateway_form_saved_payment_methods_html', $html, $this ); // @codingStandardsIgnoreLine } /** * Gets saved payment method HTML from a token. * * @since 2.6.0 * @param KKART_Payment_Token $token Payment Token. * @return string Generated payment method HTML */ public function get_saved_payment_method_option_html( $token ) { $html = sprintf( '
  • ', esc_attr( $this->id ), esc_attr( $token->get_id() ), esc_html( $token->get_display_name() ), checked( $token->is_default(), true, false ) ); return apply_filters( 'kkart_payment_gateway_get_saved_payment_method_option_html', $html, $token, $this ); } /** * Displays a radio button for entering a new payment method (new CC details) instead of using a saved method. * Only displayed when a gateway supports tokenization. * * @since 2.6.0 */ public function get_new_payment_method_option_html() { $label = apply_filters( 'kkart_payment_gateway_get_new_payment_method_option_html_label', $this->new_method_label ? $this->new_method_label : __( 'Use a new payment method', 'kkart' ), $this ); $html = sprintf( '
  • ', esc_attr( $this->id ), esc_html( $label ) ); return apply_filters( 'kkart_payment_gateway_get_new_payment_method_option_html', $html, $this ); } /** * Outputs a checkbox for saving a new payment method to the database. * * @since 2.6.0 */ public function save_payment_method_checkbox() { $html = sprintf( '

    ', esc_attr( $this->id ), esc_html__( 'Save to account', 'kkart' ) ); echo apply_filters( 'kkart_payment_gateway_save_new_payment_method_option_html', $html, $this ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Add payment method via account screen. This should be extended by gateway plugins. * * @since 3.2.0 Included here from 3.2.0, but supported from 3.0.0. * @return array */ public function add_payment_method() { return array( 'result' => 'failure', 'redirect' => kkart_get_endpoint_url( 'payment-methods' ), ); } } PK!Ҋss)abstracts/abstract-kkart-settings-api.phpnu[id, array_map( array( $this, 'set_defaults' ), $this->form_fields ) ); } /** * Set default required properties for each field. * * @param array $field Setting field array. * @return array */ protected function set_defaults( $field ) { if ( ! isset( $field['default'] ) ) { $field['default'] = ''; } return $field; } /** * Output the admin options table. */ public function admin_options() { echo '' . $this->generate_settings_html( $this->get_form_fields(), false ) . '
    '; // WPCS: XSS ok. } /** * Initialise settings form fields. * * Add an array of fields to be displayed on the gateway's settings screen. * * @since 1.0.0 */ public function init_form_fields() {} /** * Return the name of the option in the WP DB. * * @since 2.6.0 * @return string */ public function get_option_key() { return $this->plugin_id . $this->id . '_settings'; } /** * Get a fields type. Defaults to "text" if not set. * * @param array $field Field key. * @return string */ public function get_field_type( $field ) { return empty( $field['type'] ) ? 'text' : $field['type']; } /** * Get a fields default value. Defaults to "" if not set. * * @param array $field Field key. * @return string */ public function get_field_default( $field ) { return empty( $field['default'] ) ? '' : $field['default']; } /** * Get a field's posted and validated value. * * @param string $key Field key. * @param array $field Field array. * @param array $post_data Posted data. * @return string */ public function get_field_value( $key, $field, $post_data = array() ) { $type = $this->get_field_type( $field ); $field_key = $this->get_field_key( $key ); $post_data = empty( $post_data ) ? $_POST : $post_data; // WPCS: CSRF ok, input var ok. $value = isset( $post_data[ $field_key ] ) ? $post_data[ $field_key ] : null; if ( isset( $field['sanitize_callback'] ) && is_callable( $field['sanitize_callback'] ) ) { return call_user_func( $field['sanitize_callback'], $value ); } // Look for a validate_FIELDID_field method for special handling. if ( is_callable( array( $this, 'validate_' . $key . '_field' ) ) ) { return $this->{'validate_' . $key . '_field'}( $key, $value ); } // Look for a validate_FIELDTYPE_field method. if ( is_callable( array( $this, 'validate_' . $type . '_field' ) ) ) { return $this->{'validate_' . $type . '_field'}( $key, $value ); } // Fallback to text. return $this->validate_text_field( $key, $value ); } /** * Sets the POSTed data. This method can be used to set specific data, instead of taking it from the $_POST array. * * @param array $data Posted data. */ public function set_post_data( $data = array() ) { $this->data = $data; } /** * Returns the POSTed data, to be used to save the settings. * * @return array */ public function get_post_data() { if ( ! empty( $this->data ) && is_array( $this->data ) ) { return $this->data; } return $_POST; // WPCS: CSRF ok, input var ok. } /** * Update a single option. * * @since 3.4.0 * @param string $key Option key. * @param mixed $value Value to set. * @return bool was anything saved? */ public function update_option( $key, $value = '' ) { if ( empty( $this->settings ) ) { $this->init_settings(); } $this->settings[ $key ] = $value; return update_option( $this->get_option_key(), apply_filters( 'kkart_settings_api_sanitized_fields_' . $this->id, $this->settings ), 'yes' ); } /** * Processes and saves options. * If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out. * * @return bool was anything saved? */ public function process_admin_options() { $this->init_settings(); $post_data = $this->get_post_data(); foreach ( $this->get_form_fields() as $key => $field ) { if ( 'title' !== $this->get_field_type( $field ) ) { try { $this->settings[ $key ] = $this->get_field_value( $key, $field, $post_data ); } catch ( Exception $e ) { $this->add_error( $e->getMessage() ); } } } return update_option( $this->get_option_key(), apply_filters( 'kkart_settings_api_sanitized_fields_' . $this->id, $this->settings ), 'yes' ); } /** * Add an error message for display in admin on save. * * @param string $error Error message. */ public function add_error( $error ) { $this->errors[] = $error; } /** * Get admin error messages. */ public function get_errors() { return $this->errors; } /** * Display admin error messages. */ public function display_errors() { if ( $this->get_errors() ) { echo '
    '; foreach ( $this->get_errors() as $error ) { echo '

    ' . wp_kses_post( $error ) . '

    '; } echo '
    '; } } /** * Initialise Settings. * * Store all settings in a single database entry * and make sure the $settings array is either the default * or the settings stored in the database. * * @since 1.0.0 * @uses get_option(), add_option() */ public function init_settings() { $this->settings = get_option( $this->get_option_key(), null ); // If there are no settings defined, use defaults. if ( ! is_array( $this->settings ) ) { $form_fields = $this->get_form_fields(); $this->settings = array_merge( array_fill_keys( array_keys( $form_fields ), '' ), wp_list_pluck( $form_fields, 'default' ) ); } } /** * Get option from DB. * * Gets an option from the settings API, using defaults if necessary to prevent undefined notices. * * @param string $key Option key. * @param mixed $empty_value Value when empty. * @return string The value specified for the option or a default value for the option. */ public function get_option( $key, $empty_value = null ) { if ( empty( $this->settings ) ) { $this->init_settings(); } // Get option default if unset. if ( ! isset( $this->settings[ $key ] ) ) { $form_fields = $this->get_form_fields(); $this->settings[ $key ] = isset( $form_fields[ $key ] ) ? $this->get_field_default( $form_fields[ $key ] ) : ''; } if ( ! is_null( $empty_value ) && '' === $this->settings[ $key ] ) { $this->settings[ $key ] = $empty_value; } return $this->settings[ $key ]; } /** * Prefix key for settings. * * @param string $key Field key. * @return string */ public function get_field_key( $key ) { return $this->plugin_id . $this->id . '_' . $key; } /** * Generate Settings HTML. * * Generate the HTML for the fields on the "settings" screen. * * @param array $form_fields (default: array()) Array of form fields. * @param bool $echo Echo or return. * @return string the html for the settings * @since 1.0.0 * @uses method_exists() */ public function generate_settings_html( $form_fields = array(), $echo = true ) { if ( empty( $form_fields ) ) { $form_fields = $this->get_form_fields(); } $html = ''; foreach ( $form_fields as $k => $v ) { $type = $this->get_field_type( $v ); if ( method_exists( $this, 'generate_' . $type . '_html' ) ) { $html .= $this->{'generate_' . $type . '_html'}( $k, $v ); } else { $html .= $this->generate_text_html( $k, $v ); } } if ( $echo ) { echo $html; // WPCS: XSS ok. } else { return $html; } } /** * Get HTML for tooltips. * * @param array $data Data for the tooltip. * @return string */ public function get_tooltip_html( $data ) { if ( true === $data['desc_tip'] ) { $tip = $data['description']; } elseif ( ! empty( $data['desc_tip'] ) ) { $tip = $data['desc_tip']; } else { $tip = ''; } return $tip ? kkart_help_tip( $tip, true ) : ''; } /** * Get HTML for descriptions. * * @param array $data Data for the description. * @return string */ public function get_description_html( $data ) { if ( true === $data['desc_tip'] ) { $description = ''; } elseif ( ! empty( $data['desc_tip'] ) ) { $description = $data['description']; } elseif ( ! empty( $data['description'] ) ) { $description = $data['description']; } else { $description = ''; } return $description ? '

    ' . wp_kses_post( $description ) . '

    ' . "\n" : ''; } /** * Get custom attributes. * * @param array $data Field data. * @return string */ public function get_custom_attribute_html( $data ) { $custom_attributes = array(); if ( ! empty( $data['custom_attributes'] ) && is_array( $data['custom_attributes'] ) ) { foreach ( $data['custom_attributes'] as $attribute => $attribute_value ) { $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"'; } } return implode( ' ', $custom_attributes ); } /** * Generate Text Input HTML. * * @param string $key Field key. * @param array $data Field data. * @since 1.0.0 * @return string */ public function generate_text_html( $key, $data ) { $field_key = $this->get_field_key( $key ); $defaults = array( 'title' => '', 'disabled' => false, 'class' => '', 'css' => '', 'placeholder' => '', 'type' => 'text', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), ); $data = wp_parse_args( $data, $defaults ); ob_start(); ?>
    get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> /> get_description_html( $data ); // WPCS: XSS ok. ?>
    get_field_key( $key ); $defaults = array( 'title' => '', 'disabled' => false, 'class' => '', 'css' => '', 'placeholder' => '', 'type' => 'text', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), ); $data = wp_parse_args( $data, $defaults ); ob_start(); ?>
    get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> /> get_description_html( $data ); // WPCS: XSS ok. ?>
    get_field_key( $key ); $defaults = array( 'title' => '', 'disabled' => false, 'class' => '', 'css' => '', 'placeholder' => '', 'type' => 'text', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), ); $data = wp_parse_args( $data, $defaults ); ob_start(); ?>
    get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> /> get_description_html( $data ); // WPCS: XSS ok. ?>
    generate_text_html( $key, $data ); } /** * Generate Color Picker Input HTML. * * @param string $key Field key. * @param array $data Field data. * @since 1.0.0 * @return string */ public function generate_color_html( $key, $data ) { $field_key = $this->get_field_key( $key ); $defaults = array( 'title' => '', 'disabled' => false, 'class' => '', 'css' => '', 'placeholder' => '', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), ); $data = wp_parse_args( $data, $defaults ); ob_start(); ?>
      get_custom_attribute_html( $data ); // WPCS: XSS ok. ?> /> get_description_html( $data ); // WPCS: XSS ok. ?>
    get_field_key( $key ); $defaults = array( 'title' => '', 'disabled' => false, 'class' => '', 'css' => '', 'placeholder' => '', 'type' => 'text', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), ); $data = wp_parse_args( $data, $defaults ); ob_start(); ?>
    get_description_html( $data ); // WPCS: XSS ok. ?>
    get_field_key( $key ); $defaults = array( 'title' => '', 'label' => '', 'disabled' => false, 'class' => '', 'css' => '', 'type' => 'text', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), ); $data = wp_parse_args( $data, $defaults ); if ( ! $data['label'] ) { $data['label'] = $data['title']; } ob_start(); ?>

    get_description_html( $data ); // WPCS: XSS ok. ?>
    get_field_key( $key ); $defaults = array( 'title' => '', 'disabled' => false, 'class' => '', 'css' => '', 'placeholder' => '', 'type' => 'text', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), 'options' => array(), ); $data = wp_parse_args( $data, $defaults ); ob_start(); ?>
    get_description_html( $data ); // WPCS: XSS ok. ?>
    get_field_key( $key ); $defaults = array( 'title' => '', 'disabled' => false, 'class' => '', 'css' => '', 'placeholder' => '', 'type' => 'text', 'desc_tip' => false, 'description' => '', 'custom_attributes' => array(), 'select_buttons' => false, 'options' => array(), ); $data = wp_parse_args( $data, $defaults ); $value = (array) $this->get_option( $key, array() ); ob_start(); ?>
    get_description_html( $data ); // WPCS: XSS ok. ?>
    get_field_key( $key ); $defaults = array( 'title' => '', 'class' => '', ); $data = wp_parse_args( $data, $defaults ); ob_start(); ?>

    array( 'src' => true, 'style' => true, 'id' => true, 'class' => true, ), ), wp_kses_allowed_html( 'post' ) ) ); } /** * Validate Checkbox Field. * * If not set, return "no", otherwise return "yes". * * @param string $key Field key. * @param string $value Posted Value. * @return string */ public function validate_checkbox_field( $key, $value ) { return ! is_null( $value ) ? 'yes' : 'no'; } /** * Validate Select Field. * * @param string $key Field key. * @param string $value Posted Value. * @return string */ public function validate_select_field( $key, $value ) { $value = is_null( $value ) ? '' : $value; return kkart_clean( stripslashes( $value ) ); } /** * Validate Multiselect Field. * * @param string $key Field key. * @param string $value Posted Value. * @return string|array */ public function validate_multiselect_field( $key, $value ) { return is_array( $value ) ? array_map( 'kkart_clean', array_map( 'stripslashes', $value ) ) : ''; } /** * Validate the data on the "Settings" form. * * @deprecated 2.6.0 No longer used. * @param array $form_fields Array of fields. */ public function validate_settings_fields( $form_fields = array() ) { kkart_deprecated_function( 'validate_settings_fields', '2.6' ); } /** * Format settings if needed. * * @deprecated 2.6.0 Unused. * @param array $value Value to format. * @return array */ public function format_settings( $value ) { kkart_deprecated_function( 'format_settings', '2.6' ); return $value; } } PK!pOO!abstracts/abstract-kkart-data.phpnu[data = array_merge( $this->data, $this->extra_data ); $this->default_data = $this->data; } /** * Only store the object ID to avoid serializing the data object instance. * * @return array */ public function __sleep() { return array( 'id' ); } /** * Re-run the constructor with the object ID. * * If the object no longer exists, remove the ID. */ public function __wakeup() { try { $this->__construct( absint( $this->id ) ); } catch ( Exception $e ) { $this->set_id( 0 ); $this->set_object_read( true ); } } /** * When the object is cloned, make sure meta is duplicated correctly. * * @since 3.0.2 */ public function __clone() { $this->maybe_read_meta_data(); if ( ! empty( $this->meta_data ) ) { foreach ( $this->meta_data as $array_key => $meta ) { $this->meta_data[ $array_key ] = clone $meta; if ( ! empty( $meta->id ) ) { $this->meta_data[ $array_key ]->id = null; } } } } /** * Get the data store. * * @since 3.0.0 * @return object */ public function get_data_store() { return $this->data_store; } /** * Returns the unique ID for this object. * * @since 2.6.0 * @return int */ public function get_id() { return $this->id; } /** * Delete an object, set the ID to 0, and return result. * * @since 2.6.0 * @param bool $force_delete Should the date be deleted permanently. * @return bool result */ public function delete( $force_delete = false ) { if ( $this->data_store ) { $this->data_store->delete( $this, array( 'force_delete' => $force_delete ) ); $this->set_id( 0 ); return true; } return false; } /** * Save should create or update based on object existence. * * @since 2.6.0 * @return int */ public function save() { if ( ! $this->data_store ) { return $this->get_id(); } /** * Trigger action before saving to the DB. Allows you to adjust object props before save. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_before_' . $this->object_type . '_object_save', $this, $this->data_store ); if ( $this->get_id() ) { $this->data_store->update( $this ); } else { $this->data_store->create( $this ); } /** * Trigger action after saving to the DB. * * @param KKART_Data $this The object being saved. * @param KKART_Data_Store_WP $data_store THe data store persisting the data. */ do_action( 'kkart_after_' . $this->object_type . '_object_save', $this, $this->data_store ); return $this->get_id(); } /** * Change data to JSON format. * * @since 2.6.0 * @return string Data in JSON format. */ public function __toString() { return wp_json_encode( $this->get_data() ); } /** * Returns all data for this object. * * @since 2.6.0 * @return array */ public function get_data() { return array_merge( array( 'id' => $this->get_id() ), $this->data, array( 'meta_data' => $this->get_meta_data() ) ); } /** * Returns array of expected data keys for this object. * * @since 3.0.0 * @return array */ public function get_data_keys() { return array_keys( $this->data ); } /** * Returns all "extra" data keys for an object (for sub objects like product types). * * @since 3.0.0 * @return array */ public function get_extra_data_keys() { return array_keys( $this->extra_data ); } /** * Filter null meta values from array. * * @since 3.0.0 * @param mixed $meta Meta value to check. * @return bool */ protected function filter_null_meta( $meta ) { return ! is_null( $meta->value ); } /** * Get All Meta Data. * * @since 2.6.0 * @return array of objects. */ public function get_meta_data() { $this->maybe_read_meta_data(); return array_values( array_filter( $this->meta_data, array( $this, 'filter_null_meta' ) ) ); } /** * Check if the key is an internal one. * * @since 3.2.0 * @param string $key Key to check. * @return bool true if it's an internal key, false otherwise */ protected function is_internal_meta_key( $key ) { $internal_meta_key = ! empty( $key ) && $this->data_store && in_array( $key, $this->data_store->get_internal_meta_keys(), true ); if ( ! $internal_meta_key ) { return false; } $has_setter_or_getter = is_callable( array( $this, 'set_' . $key ) ) || is_callable( array( $this, 'get_' . $key ) ); if ( ! $has_setter_or_getter ) { return false; } /* translators: %s: $key Key to check */ kkart_doing_it_wrong( __FUNCTION__, sprintf( __( 'Generic add/update/get meta methods should not be used for internal meta data, including "%s". Use getters and setters.', 'kkart' ), $key ), '3.2.0' ); return true; } /** * Get Meta Data by Key. * * @since 2.6.0 * @param string $key Meta Key. * @param bool $single return first found meta with key, or all with $key. * @param string $context What the value is for. Valid values are view and edit. * @return mixed */ public function get_meta( $key = '', $single = true, $context = 'view' ) { if ( $this->is_internal_meta_key( $key ) ) { $function = 'get_' . $key; if ( is_callable( array( $this, $function ) ) ) { return $this->{$function}(); } } $this->maybe_read_meta_data(); $meta_data = $this->get_meta_data(); $array_keys = array_keys( wp_list_pluck( $meta_data, 'key' ), $key, true ); $value = $single ? '' : array(); if ( ! empty( $array_keys ) ) { // We don't use the $this->meta_data property directly here because we don't want meta with a null value (i.e. meta which has been deleted via $this->delete_meta_data()). if ( $single ) { $value = $meta_data[ current( $array_keys ) ]->value; } else { $value = array_intersect_key( $meta_data, array_flip( $array_keys ) ); } } if ( 'view' === $context ) { $value = apply_filters( $this->get_hook_prefix() . $key, $value, $this ); } return $value; } /** * See if meta data exists, since get_meta always returns a '' or array(). * * @since 3.0.0 * @param string $key Meta Key. * @return boolean */ public function meta_exists( $key = '' ) { $this->maybe_read_meta_data(); $array_keys = wp_list_pluck( $this->get_meta_data(), 'key' ); return in_array( $key, $array_keys, true ); } /** * Set all meta data from array. * * @since 2.6.0 * @param array $data Key/Value pairs. */ public function set_meta_data( $data ) { if ( ! empty( $data ) && is_array( $data ) ) { $this->maybe_read_meta_data(); foreach ( $data as $meta ) { $meta = (array) $meta; if ( isset( $meta['key'], $meta['value'], $meta['id'] ) ) { $this->meta_data[] = new KKART_Meta_Data( array( 'id' => $meta['id'], 'key' => $meta['key'], 'value' => $meta['value'], ) ); } } } } /** * Add meta data. * * @since 2.6.0 * * @param string $key Meta key. * @param string|array $value Meta value. * @param bool $unique Should this be a unique key?. */ public function add_meta_data( $key, $value, $unique = false ) { if ( $this->is_internal_meta_key( $key ) ) { $function = 'set_' . $key; if ( is_callable( array( $this, $function ) ) ) { return $this->{$function}( $value ); } } $this->maybe_read_meta_data(); if ( $unique ) { $this->delete_meta_data( $key ); } $this->meta_data[] = new KKART_Meta_Data( array( 'key' => $key, 'value' => $value, ) ); } /** * Update meta data by key or ID, if provided. * * @since 2.6.0 * * @param string $key Meta key. * @param string|array $value Meta value. * @param int $meta_id Meta ID. */ public function update_meta_data( $key, $value, $meta_id = 0 ) { if ( $this->is_internal_meta_key( $key ) ) { $function = 'set_' . $key; if ( is_callable( array( $this, $function ) ) ) { return $this->{$function}( $value ); } } $this->maybe_read_meta_data(); $array_key = false; if ( $meta_id ) { $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), $meta_id, true ); $array_key = $array_keys ? current( $array_keys ) : false; } else { // Find matches by key. $matches = array(); foreach ( $this->meta_data as $meta_data_array_key => $meta ) { if ( $meta->key === $key ) { $matches[] = $meta_data_array_key; } } if ( ! empty( $matches ) ) { // Set matches to null so only one key gets the new value. foreach ( $matches as $meta_data_array_key ) { $this->meta_data[ $meta_data_array_key ]->value = null; } $array_key = current( $matches ); } } if ( false !== $array_key ) { $meta = $this->meta_data[ $array_key ]; $meta->key = $key; $meta->value = $value; } else { $this->add_meta_data( $key, $value, true ); } } /** * Delete meta data. * * @since 2.6.0 * @param string $key Meta key. */ public function delete_meta_data( $key ) { $this->maybe_read_meta_data(); $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'key' ), $key, true ); if ( $array_keys ) { foreach ( $array_keys as $array_key ) { $this->meta_data[ $array_key ]->value = null; } } } /** * Delete meta data. * * @since 2.6.0 * @param int $mid Meta ID. */ public function delete_meta_data_by_mid( $mid ) { $this->maybe_read_meta_data(); $array_keys = array_keys( wp_list_pluck( $this->meta_data, 'id' ), (int) $mid, true ); if ( $array_keys ) { foreach ( $array_keys as $array_key ) { $this->meta_data[ $array_key ]->value = null; } } } /** * Read meta data if null. * * @since 3.0.0 */ protected function maybe_read_meta_data() { if ( is_null( $this->meta_data ) ) { $this->read_meta_data(); } } /** * Read Meta Data from the database. Ignore any internal properties. * Uses it's own caches because get_metadata does not provide meta_ids. * * @since 2.6.0 * @param bool $force_read True to force a new DB read (and update cache). */ public function read_meta_data( $force_read = false ) { $this->meta_data = array(); $cache_loaded = false; if ( ! $this->get_id() ) { return; } if ( ! $this->data_store ) { return; } if ( ! empty( $this->cache_group ) ) { // Prefix by group allows invalidation by group until https://core.trac.wordpress.org/ticket/4476 is implemented. $cache_key = KKART_Cache_Helper::get_cache_prefix( $this->cache_group ) . KKART_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id(); } if ( ! $force_read ) { if ( ! empty( $this->cache_group ) ) { $cached_meta = wp_cache_get( $cache_key, $this->cache_group ); $cache_loaded = ! empty( $cached_meta ); } } $raw_meta_data = $cache_loaded ? $cached_meta : $this->data_store->read_meta( $this ); if ( $raw_meta_data ) { foreach ( $raw_meta_data as $meta ) { $this->meta_data[] = new KKART_Meta_Data( array( 'id' => (int) $meta->meta_id, 'key' => $meta->meta_key, 'value' => maybe_unserialize( $meta->meta_value ), ) ); } if ( ! $cache_loaded && ! empty( $this->cache_group ) ) { wp_cache_set( $cache_key, $raw_meta_data, $this->cache_group ); } } } /** * Update Meta Data in the database. * * @since 2.6.0 */ public function save_meta_data() { if ( ! $this->data_store || is_null( $this->meta_data ) ) { return; } foreach ( $this->meta_data as $array_key => $meta ) { if ( is_null( $meta->value ) ) { if ( ! empty( $meta->id ) ) { $this->data_store->delete_meta( $this, $meta ); unset( $this->meta_data[ $array_key ] ); } } elseif ( empty( $meta->id ) ) { $meta->id = $this->data_store->add_meta( $this, $meta ); $meta->apply_changes(); } else { if ( $meta->get_changes() ) { $this->data_store->update_meta( $this, $meta ); $meta->apply_changes(); } } } if ( ! empty( $this->cache_group ) ) { $cache_key = KKART_Cache_Helper::get_cache_prefix( $this->cache_group ) . KKART_Cache_Helper::get_cache_prefix( 'object_' . $this->get_id() ) . 'object_meta_' . $this->get_id(); wp_cache_delete( $cache_key, $this->cache_group ); } } /** * Set ID. * * @since 3.0.0 * @param int $id ID. */ public function set_id( $id ) { $this->id = absint( $id ); } /** * Set all props to default values. * * @since 3.0.0 */ public function set_defaults() { $this->data = $this->default_data; $this->changes = array(); $this->set_object_read( false ); } /** * Set object read property. * * @since 3.0.0 * @param boolean $read Should read?. */ public function set_object_read( $read = true ) { $this->object_read = (bool) $read; } /** * Get object read property. * * @since 3.0.0 * @return boolean */ public function get_object_read() { return (bool) $this->object_read; } /** * Set a collection of props in one go, collect any errors, and return the result. * Only sets using public methods. * * @since 3.0.0 * * @param array $props Key value pairs to set. Key is the prop and should map to a setter function name. * @param string $context In what context to run this. * * @return bool|WP_Error */ public function set_props( $props, $context = 'set' ) { $errors = false; foreach ( $props as $prop => $value ) { try { /** * Checks if the prop being set is allowed, and the value is not null. */ if ( is_null( $value ) || in_array( $prop, array( 'prop', 'date_prop', 'meta_data' ), true ) ) { continue; } $setter = "set_$prop"; if ( is_callable( array( $this, $setter ) ) ) { $this->{$setter}( $value ); } } catch ( KKART_Data_Exception $e ) { if ( ! $errors ) { $errors = new WP_Error(); } $errors->add( $e->getErrorCode(), $e->getMessage() ); } } return $errors && count( $errors->get_error_codes() ) ? $errors : true; } /** * Sets a prop for a setter method. * * This stores changes in a special array so we can track what needs saving * the the DB later. * * @since 3.0.0 * @param string $prop Name of prop to set. * @param mixed $value Value of the prop. */ protected function set_prop( $prop, $value ) { if ( array_key_exists( $prop, $this->data ) ) { if ( true === $this->object_read ) { if ( $value !== $this->data[ $prop ] || array_key_exists( $prop, $this->changes ) ) { $this->changes[ $prop ] = $value; } } else { $this->data[ $prop ] = $value; } } } /** * Return data changes only. * * @since 3.0.0 * @return array */ public function get_changes() { return $this->changes; } /** * Merge changes with data and clear. * * @since 3.0.0 */ public function apply_changes() { $this->data = array_replace_recursive( $this->data, $this->changes ); // @codingStandardsIgnoreLine $this->changes = array(); } /** * Prefix for action and filter hooks on data. * * @since 3.0.0 * @return string */ protected function get_hook_prefix() { return 'kkart_' . $this->object_type . '_get_'; } /** * Gets a prop for a getter method. * * Gets the value from either current pending changes, or the data itself. * Context controls what happens to the value before it's returned. * * @since 3.0.0 * @param string $prop Name of prop to get. * @param string $context What the value is for. Valid values are view and edit. * @return mixed */ protected function get_prop( $prop, $context = 'view' ) { $value = null; if ( array_key_exists( $prop, $this->data ) ) { $value = array_key_exists( $prop, $this->changes ) ? $this->changes[ $prop ] : $this->data[ $prop ]; if ( 'view' === $context ) { $value = apply_filters( $this->get_hook_prefix() . $prop, $value, $this ); } } return $value; } /** * Sets a date prop whilst handling formatting and datetime objects. * * @since 3.0.0 * @param string $prop Name of prop to set. * @param string|integer $value Value of the prop. */ protected function set_date_prop( $prop, $value ) { try { if ( empty( $value ) ) { $this->set_prop( $prop, null ); return; } if ( is_a( $value, 'KKART_DateTime' ) ) { $datetime = $value; } elseif ( is_numeric( $value ) ) { // Timestamps are handled as UTC timestamps in all cases. $datetime = new KKART_DateTime( "@{$value}", new DateTimeZone( 'UTC' ) ); } else { // Strings are defined in local WP timezone. Convert to UTC. if ( 1 === preg_match( '/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(Z|((-|\+)\d{2}:\d{2}))$/', $value, $date_bits ) ) { $offset = ! empty( $date_bits[7] ) ? iso8601_timezone_to_offset( $date_bits[7] ) : kkart_timezone_offset(); $timestamp = gmmktime( $date_bits[4], $date_bits[5], $date_bits[6], $date_bits[2], $date_bits[3], $date_bits[1] ) - $offset; } else { $timestamp = kkart_string_to_timestamp( get_gmt_from_date( gmdate( 'Y-m-d H:i:s', kkart_string_to_timestamp( $value ) ) ) ); } $datetime = new KKART_DateTime( "@{$timestamp}", new DateTimeZone( 'UTC' ) ); } // Set local timezone or offset. if ( get_option( 'timezone_string' ) ) { $datetime->setTimezone( new DateTimeZone( kkart_timezone_string() ) ); } else { $datetime->set_utc_offset( kkart_timezone_offset() ); } $this->set_prop( $prop, $datetime ); } catch ( Exception $e ) {} // @codingStandardsIgnoreLine. } /** * When invalid data is found, throw an exception unless reading from the DB. * * @throws KKART_Data_Exception Data Exception. * @since 3.0.0 * @param string $code Error code. * @param string $message Error message. * @param int $http_status_code HTTP status code. * @param array $data Extra error data. */ protected function error( $code, $message, $http_status_code = 400, $data = array() ) { throw new KKART_Data_Exception( $code, $message, $http_status_code, $data ); } } PK!\ӜXX$abstracts/abstract-kkart-privacy.phpnu[name = $name; $this->export_priority = $export_priority; $this->erase_priority = $erase_priority; $this->init(); } /** * Hook in events. */ protected function init() { add_action( 'admin_init', array( $this, 'add_privacy_message' ) ); // We set priority to 5 to help Kkart's findings appear before those from extensions in exported items. add_filter( 'wp_privacy_personal_data_exporters', array( $this, 'register_exporters' ), $this->export_priority ); add_filter( 'wp_privacy_personal_data_erasers', array( $this, 'register_erasers' ), $this->erase_priority ); } /** * Adds the privacy message on KKART privacy page. */ public function add_privacy_message() { if ( function_exists( 'wp_add_privacy_policy_content' ) ) { $content = $this->get_privacy_message(); if ( $content ) { wp_add_privacy_policy_content( $this->name, $this->get_privacy_message() ); } } } /** * Gets the message of the privacy to display. * To be overloaded by the implementor. * * @return string */ public function get_privacy_message() { return ''; } /** * Integrate this exporter implementation within the WordPress core exporters. * * @param array $exporters List of exporter callbacks. * @return array */ public function register_exporters( $exporters = array() ) { foreach ( $this->exporters as $id => $exporter ) { $exporters[ $id ] = $exporter; } return $exporters; } /** * Integrate this eraser implementation within the WordPress core erasers. * * @param array $erasers List of eraser callbacks. * @return array */ public function register_erasers( $erasers = array() ) { foreach ( $this->erasers as $id => $eraser ) { $erasers[ $id ] = $eraser; } return $erasers; } /** * Add exporter to list of exporters. * * @param string $id ID of the Exporter. * @param string $name Exporter name. * @param string|array $callback Exporter callback. * * @return array */ public function add_exporter( $id, $name, $callback ) { $this->exporters[ $id ] = array( 'exporter_friendly_name' => $name, 'callback' => $callback, ); return $this->exporters; } /** * Add eraser to list of erasers. * * @param string $id ID of the Eraser. * @param string $name Exporter name. * @param string|array $callback Exporter callback. * * @return array */ public function add_eraser( $id, $name, $callback ) { $this->erasers[ $id ] = array( 'eraser_friendly_name' => $name, 'callback' => $callback, ); return $this->erasers; } } PK!\class-kkart-product-grouped.phpnu[ array(), ); /** * Get internal type. * * @return string */ public function get_type() { return 'grouped'; } /** * Get the add to cart button text. * * @return string */ public function add_to_cart_text() { return apply_filters( 'kkart_product_add_to_cart_text', __( 'View products', 'kkart' ), $this ); } /** * Get the add to cart button text description - used in aria tags. * * @since 3.3.0 * @return string */ public function add_to_cart_description() { /* translators: %s: Product title */ return apply_filters( 'kkart_product_add_to_cart_description', sprintf( __( 'View products in the “%s” group', 'kkart' ), $this->get_name() ), $this ); } /** * Returns whether or not the product is on sale. * * @param string $context What the value is for. Valid values are view and edit. * @return bool */ public function is_on_sale( $context = 'view' ) { $children = array_filter( array_map( 'kkart_get_product', $this->get_children( $context ) ), 'kkart_products_array_filter_visible_grouped' ); $on_sale = false; foreach ( $children as $child ) { if ( $child->is_purchasable() && ! $child->has_child() && $child->is_on_sale() ) { $on_sale = true; break; } } return 'view' === $context ? apply_filters( 'kkart_product_is_on_sale', $on_sale, $this ) : $on_sale; } /** * Returns false if the product cannot be bought. * * @return bool */ public function is_purchasable() { return apply_filters( 'kkart_is_purchasable', false, $this ); } /** * Returns the price in html format. * * @param string $price (default: ''). * @return string */ public function get_price_html( $price = '' ) { $tax_display_mode = get_option( 'kkart_tax_display_shop' ); $child_prices = array(); $children = array_filter( array_map( 'kkart_get_product', $this->get_children() ), 'kkart_products_array_filter_visible_grouped' ); foreach ( $children as $child ) { if ( '' !== $child->get_price() ) { $child_prices[] = 'incl' === $tax_display_mode ? kkart_get_price_including_tax( $child ) : kkart_get_price_excluding_tax( $child ); } } if ( ! empty( $child_prices ) ) { $min_price = min( $child_prices ); $max_price = max( $child_prices ); } else { $min_price = ''; $max_price = ''; } if ( '' !== $min_price ) { if ( $min_price !== $max_price ) { $price = kkart_format_price_range( $min_price, $max_price ); } else { $price = kkart_price( $min_price ); } $is_free = 0 === $min_price && 0 === $max_price; if ( $is_free ) { $price = apply_filters( 'kkart_grouped_free_price_html', __( 'Free!', 'kkart' ), $this ); } else { $price = apply_filters( 'kkart_grouped_price_html', $price . $this->get_price_suffix(), $this, $child_prices ); } } else { $price = apply_filters( 'kkart_grouped_empty_price_html', '', $this ); } return apply_filters( 'kkart_get_price_html', $price, $this ); } /* |-------------------------------------------------------------------------- | Getters |-------------------------------------------------------------------------- | | Methods for getting data from the product object. */ /** * Return the children of this product. * * @param string $context What the value is for. Valid values are view and edit. * @return array */ public function get_children( $context = 'view' ) { return $this->get_prop( 'children', $context ); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- | | Methods for getting data from the product object. */ /** * Return the children of this product. * * @param array $children List of product children. */ public function set_children( $children ) { $this->set_prop( 'children', array_filter( wp_parse_id_list( (array) $children ) ) ); } /* |-------------------------------------------------------------------------- | Sync with children. |-------------------------------------------------------------------------- */ /** * Sync a grouped product with it's children. These sync functions sync * upwards (from child to parent) when the variation is saved. * * @param KKART_Product|int $product Product object or ID for which you wish to sync. * @param bool $save If true, the product object will be saved to the DB before returning it. * @return KKART_Product Synced product object. */ public static function sync( $product, $save = true ) { if ( ! is_a( $product, 'KKART_Product' ) ) { $product = kkart_get_product( $product ); } if ( is_a( $product, 'KKART_Product_Grouped' ) ) { $data_store = KKART_Data_Store::load( 'product-' . $product->get_type() ); $data_store->sync_price( $product ); if ( $save ) { $product->save(); } } return $product; } } PK!~~*class-kkart-register-wp-admin-settings.phpnu[object = $object; if ( 'page' === $type ) { add_filter( 'kkart_settings_groups', array( $this, 'register_page_group' ) ); add_filter( 'kkart_settings-' . $this->object->get_id(), array( $this, 'register_page_settings' ) ); } elseif ( 'email' === $type ) { add_filter( 'kkart_settings_groups', array( $this, 'register_email_group' ) ); add_filter( 'kkart_settings-email_' . $this->object->id, array( $this, 'register_email_settings' ) ); } } /** * Register's all of our different notification emails as sub groups * of email settings. * * @since 3.0.0 * @param array $groups Existing registered groups. * @return array */ public function register_email_group( $groups ) { $groups[] = array( 'id' => 'email_' . $this->object->id, 'label' => $this->object->title, 'description' => $this->object->description, 'parent_id' => 'email', ); return $groups; } /** * Registers all of the setting form fields for emails to each email type's group. * * @since 3.0.0 * @param array $settings Existing registered settings. * @return array */ public function register_email_settings( $settings ) { foreach ( $this->object->form_fields as $id => $setting ) { $setting['id'] = $id; $setting['option_key'] = array( $this->object->get_option_key(), $id ); $new_setting = $this->register_setting( $setting ); if ( $new_setting ) { $settings[] = $new_setting; } } return $settings; } /** * Registers a setting group, based on admin page ID & label as parent group. * * @since 3.0.0 * @param array $groups Array of previously registered groups. * @return array */ public function register_page_group( $groups ) { $groups[] = array( 'id' => $this->object->get_id(), 'label' => $this->object->get_label(), ); return $groups; } /** * Registers settings to a specific group. * * @since 3.0.0 * @param array $settings Existing registered settings. * @return array */ public function register_page_settings( $settings ) { /** * WP admin settings can be broken down into separate sections from * a UI standpoint. This will grab all the sections associated with * a particular setting group (like 'products') and register them * to the REST API. */ $sections = $this->object->get_sections(); if ( empty( $sections ) ) { // Default section is just an empty string, per admin page classes. $sections = array( '' ); } foreach ( $sections as $section => $section_label ) { $settings_from_section = $this->object->get_settings( $section ); foreach ( $settings_from_section as $setting ) { if ( ! isset( $setting['id'] ) ) { continue; } $setting['option_key'] = $setting['id']; $new_setting = $this->register_setting( $setting ); if ( $new_setting ) { $settings[] = $new_setting; } } } return $settings; } /** * Register a setting into the format expected for the Settings REST API. * * @since 3.0.0 * @param array $setting Setting data. * @return array|bool */ public function register_setting( $setting ) { if ( ! isset( $setting['id'] ) ) { return false; } $description = ''; if ( ! empty( $setting['desc'] ) ) { $description = $setting['desc']; } elseif ( ! empty( $setting['description'] ) ) { $description = $setting['description']; } $new_setting = array( 'id' => $setting['id'], 'label' => ( ! empty( $setting['title'] ) ? $setting['title'] : '' ), 'description' => $description, 'type' => $setting['type'], 'option_key' => $setting['option_key'], ); if ( isset( $setting['default'] ) ) { $new_setting['default'] = $setting['default']; } if ( isset( $setting['options'] ) ) { $new_setting['options'] = $setting['options']; } if ( isset( $setting['desc_tip'] ) ) { if ( true === $setting['desc_tip'] ) { $new_setting['tip'] = $description; } elseif ( ! empty( $setting['desc_tip'] ) ) { $new_setting['tip'] = $setting['desc_tip']; } } return $new_setting; } } PK!-kkart-notice-functions.phpnu[session->get( 'kkart_notices', array() ); if ( isset( $all_notices[ $notice_type ] ) ) { $notice_count = count( $all_notices[ $notice_type ] ); } elseif ( empty( $notice_type ) ) { foreach ( $all_notices as $notices ) { $notice_count += count( $notices ); } } return $notice_count; } /** * Check if a notice has already been added. * * @since 2.1 * @param string $message The text to display in the notice. * @param string $notice_type Optional. The name of the notice type - either error, success or notice. * @return bool */ function kkart_has_notice( $message, $notice_type = 'success' ) { if ( ! did_action( 'kkart_init' ) ) { kkart_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before kkart_init.', 'kkart' ), '2.3' ); return false; } $notices = KKART()->session->get( 'kkart_notices', array() ); $notices = isset( $notices[ $notice_type ] ) ? $notices[ $notice_type ] : array(); return array_search( $message, wp_list_pluck( $notices, 'notice' ), true ) !== false; } /** * Add and store a notice. * * @since 2.1 * @version 3.9.0 * @param string $message The text to display in the notice. * @param string $notice_type Optional. The name of the notice type - either error, success or notice. * @param array $data Optional notice data. */ function kkart_add_notice( $message, $notice_type = 'success', $data = array() ) { if ( ! did_action( 'kkart_init' ) ) { kkart_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before kkart_init.', 'kkart' ), '2.3' ); return; } $notices = KKART()->session->get( 'kkart_notices', array() ); // Backward compatibility. if ( 'success' === $notice_type ) { $message = apply_filters( 'kkart_add_message', $message ); } $message = apply_filters( 'kkart_add_' . $notice_type, $message ); if ( ! empty( $message ) ) { $notices[ $notice_type ][] = array( 'notice' => $message, 'data' => $data, ); } KKART()->session->set( 'kkart_notices', $notices ); } /** * Set all notices at once. * * @since 2.6.0 * @param array[] $notices Array of notices. */ function kkart_set_notices( $notices ) { if ( ! did_action( 'kkart_init' ) ) { kkart_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before kkart_init.', 'kkart' ), '2.6' ); return; } KKART()->session->set( 'kkart_notices', $notices ); } /** * Unset all notices. * * @since 2.1 */ function kkart_clear_notices() { if ( ! did_action( 'kkart_init' ) ) { kkart_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before kkart_init.', 'kkart' ), '2.3' ); return; } KKART()->session->set( 'kkart_notices', null ); } /** * Prints messages and errors which are stored in the session, then clears them. * * @since 2.1 * @param bool $return true to return rather than echo. @since 3.5.0. * @return string|null */ function kkart_print_notices( $return = false ) { if ( ! did_action( 'kkart_init' ) ) { kkart_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before kkart_init.', 'kkart' ), '2.3' ); return; } $all_notices = KKART()->session->get( 'kkart_notices', array() ); $notice_types = apply_filters( 'kkart_notice_types', array( 'error', 'success', 'notice' ) ); // Buffer output. ob_start(); foreach ( $notice_types as $notice_type ) { if ( kkart_notice_count( $notice_type ) > 0 ) { $messages = array(); foreach ( $all_notices[ $notice_type ] as $notice ) { $messages[] = isset( $notice['notice'] ) ? $notice['notice'] : $notice; } kkart_get_template( "notices/{$notice_type}.php", array( 'messages' => array_filter( $messages ), // @deprecated 3.9.0 'notices' => array_filter( $all_notices[ $notice_type ] ), ) ); } } kkart_clear_notices(); $notices = kkart_kses_notice( ob_get_clean() ); if ( $return ) { return $notices; } echo $notices; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Print a single notice immediately. * * @since 2.1 * @version 3.9.0 * @param string $message The text to display in the notice. * @param string $notice_type Optional. The singular name of the notice type - either error, success or notice. * @param array $data Optional notice data. @since 3.9.0. */ function kkart_print_notice( $message, $notice_type = 'success', $data = array() ) { if ( 'success' === $notice_type ) { $message = apply_filters( 'kkart_add_message', $message ); } $message = apply_filters( 'kkart_add_' . $notice_type, $message ); kkart_get_template( "notices/{$notice_type}.php", array( 'messages' => array( $message ), // @deprecated 3.9.0 'notices' => array( array( 'notice' => $message, 'data' => $data, ), ), ) ); } /** * Returns all queued notices, optionally filtered by a notice type. * * @since 2.1 * @version 3.9.0 * @param string $notice_type Optional. The singular name of the notice type - either error, success or notice. * @return array[] */ function kkart_get_notices( $notice_type = '' ) { if ( ! did_action( 'kkart_init' ) ) { kkart_doing_it_wrong( __FUNCTION__, __( 'This function should not be called before kkart_init.', 'kkart' ), '2.3' ); return; } $all_notices = KKART()->session->get( 'kkart_notices', array() ); if ( empty( $notice_type ) ) { $notices = $all_notices; } elseif ( isset( $all_notices[ $notice_type ] ) ) { $notices = $all_notices[ $notice_type ]; } else { $notices = array(); } return $notices; } /** * Add notices for WP Errors. * * @param WP_Error $errors Errors. */ function kkart_add_wp_error_notices( $errors ) { if ( is_wp_error( $errors ) && $errors->get_error_messages() ) { foreach ( $errors->get_error_messages() as $error ) { kkart_add_notice( $error, 'error' ); } } } /** * Filters out the same tags as wp_kses_post, but allows tabindex for element. * * @since 3.5.0 * @param string $message Content to filter through kses. * @return string */ function kkart_kses_notice( $message ) { $allowed_tags = array_replace_recursive( wp_kses_allowed_html( 'post' ), array( 'a' => array( 'tabindex' => true, ), ) ); /** * Kses notice allowed tags. * * @since 3.9.0 * @param array[]|string $allowed_tags An array of allowed HTML elements and attributes, or a context name such as 'post'. */ return wp_kses( $message, apply_filters( 'kkart_kses_notice_allowed_tags', $allowed_tags ) ); } /** * Get notice data attribute. * * @since 3.9.0 * @param array $notice Notice data. * @return string */ function kkart_get_notice_data_attr( $notice ) { if ( empty( $notice['data'] ) ) { return; } $attr = ''; foreach ( $notice['data'] as $key => $value ) { $attr .= sprintf( ' data-%1$s="%2$s"', sanitize_title( $key ), esc_attr( $value ) ); } return $attr; } PK!"class-kkart-rest-exception.phpnu[ '', 'amount' => 0, 'date_created' => null, 'date_modified' => null, 'date_expires' => null, 'discount_type' => 'fixed_cart', 'description' => '', 'usage_count' => 0, 'individual_use' => false, 'product_ids' => array(), 'excluded_product_ids' => array(), 'usage_limit' => 0, 'usage_limit_per_user' => 0, 'limit_usage_to_x_items' => null, 'free_shipping' => false, 'product_categories' => array(), 'excluded_product_categories' => array(), 'exclude_sale_items' => false, 'minimum_amount' => '', 'maximum_amount' => '', 'email_restrictions' => array(), 'used_by' => array(), 'virtual' => false, ); // Coupon message codes. const E_KKART_COUPON_INVALID_FILTERED = 100; const E_KKART_COUPON_INVALID_REMOVED = 101; const E_KKART_COUPON_NOT_YOURS_REMOVED = 102; const E_KKART_COUPON_ALREADY_APPLIED = 103; const E_KKART_COUPON_ALREADY_APPLIED_INDIV_USE_ONLY = 104; const E_KKART_COUPON_NOT_EXIST = 105; const E_KKART_COUPON_USAGE_LIMIT_REACHED = 106; const E_KKART_COUPON_EXPIRED = 107; const E_KKART_COUPON_MIN_SPEND_LIMIT_NOT_MET = 108; const E_KKART_COUPON_NOT_APPLICABLE = 109; const E_KKART_COUPON_NOT_VALID_SALE_ITEMS = 110; const E_KKART_COUPON_PLEASE_ENTER = 111; const E_KKART_COUPON_MAX_SPEND_LIMIT_MET = 112; const E_KKART_COUPON_EXCLUDED_PRODUCTS = 113; const E_KKART_COUPON_EXCLUDED_CATEGORIES = 114; const KKART_COUPON_SUCCESS = 200; const KKART_COUPON_REMOVED = 201; /** * Cache group. * * @var string */ protected $cache_group = 'coupons'; /** * Coupon constructor. Loads coupon data. * * @param mixed $data Coupon data, object, ID or code. */ public function __construct( $data = '' ) { parent::__construct( $data ); // If we already have a coupon object, read it again. if ( $data instanceof KKART_Coupon ) { $this->set_id( absint( $data->get_id() ) ); $this->read_object_from_database(); return; } // This filter allows custom coupon objects to be created on the fly. $coupon = apply_filters( 'kkart_get_shop_coupon_data', false, $data, $this ); if ( $coupon ) { $this->read_manual_coupon( $data, $coupon ); return; } // Try to load coupon using ID or code. if ( is_int( $data ) && 'shop_coupon' === get_post_type( $data ) ) { $this->set_id( $data ); } elseif ( ! empty( $data ) ) { $id = kkart_get_coupon_id_by_code( $data ); // Need to support numeric strings for backwards compatibility. if ( ! $id && 'shop_coupon' === get_post_type( $data ) ) { $this->set_id( $data ); } else { $this->set_id( $id ); $this->set_code( $data ); } } else { $this->set_object_read( true ); } $this->read_object_from_database(); } /** * If the object has an ID, read using the data store. * * @since 3.4.1 */ protected function read_object_from_database() { $this->data_store = KKART_Data_Store::load( 'coupon' ); if ( $this->get_id() > 0 ) { $this->data_store->read( $this ); } } /** * Checks the coupon type. * * @param string $type Array or string of types. * @return bool */ public function is_type( $type ) { return ( $this->get_discount_type() === $type || ( is_array( $type ) && in_array( $this->get_discount_type(), $type, true ) ) ); } /** * Prefix for action and filter hooks on data. * * @since 3.0.0 * @return string */ protected function get_hook_prefix() { return 'kkart_coupon_get_'; } /* |-------------------------------------------------------------------------- | Getters |-------------------------------------------------------------------------- | | Methods for getting data from the coupon object. | */ /** * Get coupon code. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return string */ public function get_code( $context = 'view' ) { return $this->get_prop( 'code', $context ); } /** * Get coupon description. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return string */ public function get_description( $context = 'view' ) { return $this->get_prop( 'description', $context ); } /** * Get discount type. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return string */ public function get_discount_type( $context = 'view' ) { return $this->get_prop( 'discount_type', $context ); } /** * Get coupon amount. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return float */ public function get_amount( $context = 'view' ) { return kkart_format_decimal( $this->get_prop( 'amount', $context ) ); } /** * Get coupon expiration date. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_expires( $context = 'view' ) { return $this->get_prop( 'date_expires', $context ); } /** * Get date_created * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_created( $context = 'view' ) { return $this->get_prop( 'date_created', $context ); } /** * Get date_modified * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return KKART_DateTime|NULL object if the date is set or null if there is no date. */ public function get_date_modified( $context = 'view' ) { return $this->get_prop( 'date_modified', $context ); } /** * Get coupon usage count. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return integer */ public function get_usage_count( $context = 'view' ) { return $this->get_prop( 'usage_count', $context ); } /** * Get the "indvidual use" checkbox status. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return bool */ public function get_individual_use( $context = 'view' ) { return $this->get_prop( 'individual_use', $context ); } /** * Get product IDs this coupon can apply to. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return array */ public function get_product_ids( $context = 'view' ) { return $this->get_prop( 'product_ids', $context ); } /** * Get product IDs that this coupon should not apply to. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return array */ public function get_excluded_product_ids( $context = 'view' ) { return $this->get_prop( 'excluded_product_ids', $context ); } /** * Get coupon usage limit. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return integer */ public function get_usage_limit( $context = 'view' ) { return $this->get_prop( 'usage_limit', $context ); } /** * Get coupon usage limit per customer (for a single customer) * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return integer */ public function get_usage_limit_per_user( $context = 'view' ) { return $this->get_prop( 'usage_limit_per_user', $context ); } /** * Usage limited to certain amount of items * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return integer|null */ public function get_limit_usage_to_x_items( $context = 'view' ) { return $this->get_prop( 'limit_usage_to_x_items', $context ); } /** * If this coupon grants free shipping or not. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return bool */ public function get_free_shipping( $context = 'view' ) { return $this->get_prop( 'free_shipping', $context ); } /** * Get product categories this coupon can apply to. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return array */ public function get_product_categories( $context = 'view' ) { return $this->get_prop( 'product_categories', $context ); } /** * Get product categories this coupon cannot not apply to. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return array */ public function get_excluded_product_categories( $context = 'view' ) { return $this->get_prop( 'excluded_product_categories', $context ); } /** * If this coupon should exclude items on sale. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return bool */ public function get_exclude_sale_items( $context = 'view' ) { return $this->get_prop( 'exclude_sale_items', $context ); } /** * Get minimum spend amount. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return float */ public function get_minimum_amount( $context = 'view' ) { return $this->get_prop( 'minimum_amount', $context ); } /** * Get maximum spend amount. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return float */ public function get_maximum_amount( $context = 'view' ) { return $this->get_prop( 'maximum_amount', $context ); } /** * Get emails to check customer usage restrictions. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return array */ public function get_email_restrictions( $context = 'view' ) { return $this->get_prop( 'email_restrictions', $context ); } /** * Get records of all users who have used the current coupon. * * @since 3.0.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return array */ public function get_used_by( $context = 'view' ) { return $this->get_prop( 'used_by', $context ); } /** * If the filter is added through the kkart_get_shop_coupon_data filter, it's virtual and not in the DB. * * @since 3.2.0 * @param string $context What the value is for. Valid values are 'view' and 'edit'. * @return boolean */ public function get_virtual( $context = 'view' ) { return (bool) $this->get_prop( 'virtual', $context ); } /** * Get discount amount for a cart item. * * @param float $discounting_amount Amount the coupon is being applied to. * @param array|null $cart_item Cart item being discounted if applicable. * @param boolean $single True if discounting a single qty item, false if its the line. * @return float Amount this coupon has discounted. */ public function get_discount_amount( $discounting_amount, $cart_item = null, $single = false ) { $discount = 0; $cart_item_qty = is_null( $cart_item ) ? 1 : $cart_item['quantity']; if ( $this->is_type( array( 'percent' ) ) ) { $discount = (float) $this->get_amount() * ( $discounting_amount / 100 ); } elseif ( $this->is_type( 'fixed_cart' ) && ! is_null( $cart_item ) && KKART()->cart->subtotal_ex_tax ) { /** * This is the most complex discount - we need to divide the discount between rows based on their price in. * proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows. * with no price (free) don't get discounted. * * Get item discount by dividing item cost by subtotal to get a %. * * Uses price inc tax if prices include tax to work around https://github.com/kkart/kkart/issues/7669 and https://github.com/kkart/kkart/issues/8074. */ if ( kkart_prices_include_tax() ) { $discount_percent = ( kkart_get_price_including_tax( $cart_item['data'] ) * $cart_item_qty ) / KKART()->cart->subtotal; } else { $discount_percent = ( kkart_get_price_excluding_tax( $cart_item['data'] ) * $cart_item_qty ) / KKART()->cart->subtotal_ex_tax; } $discount = ( (float) $this->get_amount() * $discount_percent ) / $cart_item_qty; } elseif ( $this->is_type( 'fixed_product' ) ) { $discount = min( $this->get_amount(), $discounting_amount ); $discount = $single ? $discount : $discount * $cart_item_qty; } return apply_filters( 'kkart_coupon_get_discount_amount', NumberUtil::round( min( $discount, $discounting_amount ), kkart_get_rounding_precision() ), $discounting_amount, $cart_item, $single, $this ); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- | | Functions for setting coupon data. These should not update anything in the | database itself and should only change what is stored in the class | object. | */ /** * Set coupon code. * * @since 3.0.0 * @param string $code Coupon code. */ public function set_code( $code ) { $this->set_prop( 'code', kkart_format_coupon_code( $code ) ); } /** * Set coupon description. * * @since 3.0.0 * @param string $description Description. */ public function set_description( $description ) { $this->set_prop( 'description', $description ); } /** * Set discount type. * * @since 3.0.0 * @param string $discount_type Discount type. */ public function set_discount_type( $discount_type ) { if ( 'percent_product' === $discount_type ) { $discount_type = 'percent'; // Backwards compatibility. } if ( ! in_array( $discount_type, array_keys( kkart_get_coupon_types() ), true ) ) { $this->error( 'coupon_invalid_discount_type', __( 'Invalid discount type', 'kkart' ) ); } $this->set_prop( 'discount_type', $discount_type ); } /** * Set amount. * * @since 3.0.0 * @param float $amount Amount. */ public function set_amount( $amount ) { $amount = kkart_format_decimal( $amount ); if ( ! is_numeric( $amount ) ) { $amount = 0; } if ( $amount < 0 ) { $this->error( 'coupon_invalid_amount', __( 'Invalid discount amount', 'kkart' ) ); } if ( 'percent' === $this->get_discount_type() && $amount > 100 ) { $this->error( 'coupon_invalid_amount', __( 'Invalid discount amount', 'kkart' ) ); } $this->set_prop( 'amount', $amount ); } /** * Set expiration date. * * @since 3.0.0 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if there is no date. */ public function set_date_expires( $date ) { $this->set_date_prop( 'date_expires', $date ); } /** * Set date_created * * @since 3.0.0 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if there is no date. */ public function set_date_created( $date ) { $this->set_date_prop( 'date_created', $date ); } /** * Set date_modified * * @since 3.0.0 * @param string|integer|null $date UTC timestamp, or ISO 8601 DateTime. If the DateTime string has no timezone or offset, WordPress site timezone will be assumed. Null if there is no date. */ public function set_date_modified( $date ) { $this->set_date_prop( 'date_modified', $date ); } /** * Set how many times this coupon has been used. * * @since 3.0.0 * @param int $usage_count Usage count. */ public function set_usage_count( $usage_count ) { $this->set_prop( 'usage_count', absint( $usage_count ) ); } /** * Set if this coupon can only be used once. * * @since 3.0.0 * @param bool $is_individual_use If is for individual use. */ public function set_individual_use( $is_individual_use ) { $this->set_prop( 'individual_use', (bool) $is_individual_use ); } /** * Set the product IDs this coupon can be used with. * * @since 3.0.0 * @param array $product_ids Products IDs. */ public function set_product_ids( $product_ids ) { $this->set_prop( 'product_ids', array_filter( wp_parse_id_list( (array) $product_ids ) ) ); } /** * Set the product IDs this coupon cannot be used with. * * @since 3.0.0 * @param array $excluded_product_ids Exclude product IDs. */ public function set_excluded_product_ids( $excluded_product_ids ) { $this->set_prop( 'excluded_product_ids', array_filter( wp_parse_id_list( (array) $excluded_product_ids ) ) ); } /** * Set the amount of times this coupon can be used. * * @since 3.0.0 * @param int $usage_limit Usage limit. */ public function set_usage_limit( $usage_limit ) { $this->set_prop( 'usage_limit', absint( $usage_limit ) ); } /** * Set the amount of times this coupon can be used per user. * * @since 3.0.0 * @param int $usage_limit Usage limit. */ public function set_usage_limit_per_user( $usage_limit ) { $this->set_prop( 'usage_limit_per_user', absint( $usage_limit ) ); } /** * Set usage limit to x number of items. * * @since 3.0.0 * @param int|null $limit_usage_to_x_items Limit usage to X items. */ public function set_limit_usage_to_x_items( $limit_usage_to_x_items ) { $this->set_prop( 'limit_usage_to_x_items', is_null( $limit_usage_to_x_items ) ? null : absint( $limit_usage_to_x_items ) ); } /** * Set if this coupon enables free shipping or not. * * @since 3.0.0 * @param bool $free_shipping If grant free shipping. */ public function set_free_shipping( $free_shipping ) { $this->set_prop( 'free_shipping', (bool) $free_shipping ); } /** * Set the product category IDs this coupon can be used with. * * @since 3.0.0 * @param array $product_categories List of product categories. */ public function set_product_categories( $product_categories ) { $this->set_prop( 'product_categories', array_filter( wp_parse_id_list( (array) $product_categories ) ) ); } /** * Set the product category IDs this coupon cannot be used with. * * @since 3.0.0 * @param array $excluded_product_categories List of excluded product categories. */ public function set_excluded_product_categories( $excluded_product_categories ) { $this->set_prop( 'excluded_product_categories', array_filter( wp_parse_id_list( (array) $excluded_product_categories ) ) ); } /** * Set if this coupon should excluded sale items or not. * * @since 3.0.0 * @param bool $exclude_sale_items If should exclude sale items. */ public function set_exclude_sale_items( $exclude_sale_items ) { $this->set_prop( 'exclude_sale_items', (bool) $exclude_sale_items ); } /** * Set the minimum spend amount. * * @since 3.0.0 * @param float $amount Minium amount. */ public function set_minimum_amount( $amount ) { $this->set_prop( 'minimum_amount', kkart_format_decimal( $amount ) ); } /** * Set the maximum spend amount. * * @since 3.0.0 * @param float $amount Maximum amount. */ public function set_maximum_amount( $amount ) { $this->set_prop( 'maximum_amount', kkart_format_decimal( $amount ) ); } /** * Set email restrictions. * * @since 3.0.0 * @param array $emails List of emails. */ public function set_email_restrictions( $emails = array() ) { $emails = array_filter( array_map( 'sanitize_email', array_map( 'strtolower', (array) $emails ) ) ); foreach ( $emails as $email ) { if ( ! is_email( $email ) ) { $this->error( 'coupon_invalid_email_address', __( 'Invalid email address restriction', 'kkart' ) ); } } $this->set_prop( 'email_restrictions', $emails ); } /** * Set which users have used this coupon. * * @since 3.0.0 * @param array $used_by List of user IDs. */ public function set_used_by( $used_by ) { $this->set_prop( 'used_by', array_filter( $used_by ) ); } /** * Set coupon virtual state. * * @param boolean $virtual Whether it is virtual or not. * @since 3.2.0 */ public function set_virtual( $virtual ) { $this->set_prop( 'virtual', (bool) $virtual ); } /* |-------------------------------------------------------------------------- | Other Actions |-------------------------------------------------------------------------- */ /** * Developers can programmatically return coupons. This function will read those values into our KKART_Coupon class. * * @since 3.0.0 * @param string $code Coupon code. * @param array $coupon Array of coupon properties. */ public function read_manual_coupon( $code, $coupon ) { foreach ( $coupon as $key => $value ) { switch ( $key ) { case 'excluded_product_ids': case 'exclude_product_ids': if ( ! is_array( $coupon[ $key ] ) ) { kkart_doing_it_wrong( $key, $key . ' should be an array instead of a string.', '3.0' ); $coupon['excluded_product_ids'] = kkart_string_to_array( $value ); } break; case 'exclude_product_categories': case 'excluded_product_categories': if ( ! is_array( $coupon[ $key ] ) ) { kkart_doing_it_wrong( $key, $key . ' should be an array instead of a string.', '3.0' ); $coupon['excluded_product_categories'] = kkart_string_to_array( $value ); } break; case 'product_ids': if ( ! is_array( $coupon[ $key ] ) ) { kkart_doing_it_wrong( $key, $key . ' should be an array instead of a string.', '3.0' ); $coupon[ $key ] = kkart_string_to_array( $value ); } break; case 'individual_use': case 'free_shipping': case 'exclude_sale_items': if ( ! is_bool( $coupon[ $key ] ) ) { kkart_doing_it_wrong( $key, $key . ' should be true or false instead of yes or no.', '3.0' ); $coupon[ $key ] = kkart_string_to_bool( $value ); } break; case 'expiry_date': $coupon['date_expires'] = $value; break; } } $this->set_props( $coupon ); $this->set_code( $code ); $this->set_id( 0 ); $this->set_virtual( true ); } /** * Increase usage count for current coupon. * * @param string $used_by Either user ID or billing email. * @param KKART_Order $order If provided, will clear the coupons held by this order. */ public function increase_usage_count( $used_by = '', $order = null ) { if ( $this->get_id() && $this->data_store ) { $new_count = $this->data_store->increase_usage_count( $this, $used_by, $order ); // Bypass set_prop and remove pending changes since the data store saves the count already. $this->data['usage_count'] = $new_count; if ( isset( $this->changes['usage_count'] ) ) { unset( $this->changes['usage_count'] ); } } } /** * Decrease usage count for current coupon. * * @param string $used_by Either user ID or billing email. */ public function decrease_usage_count( $used_by = '' ) { if ( $this->get_id() && $this->get_usage_count() > 0 && $this->data_store ) { $new_count = $this->data_store->decrease_usage_count( $this, $used_by ); // Bypass set_prop and remove pending changes since the data store saves the count already. $this->data['usage_count'] = $new_count; if ( isset( $this->changes['usage_count'] ) ) { unset( $this->changes['usage_count'] ); } } } /* |-------------------------------------------------------------------------- | Validation & Error Handling |-------------------------------------------------------------------------- */ /** * Returns the error_message string. * @return string */ public function get_error_message() { return $this->error_message; } /** * Check if a coupon is valid for the cart. * * @deprecated 3.2.0 In favor of KKART_Discounts->is_coupon_valid. * @return bool */ public function is_valid() { $discounts = new KKART_Discounts( KKART()->cart ); $valid = $discounts->is_coupon_valid( $this ); if ( is_wp_error( $valid ) ) { $this->error_message = $valid->get_error_message(); return false; } return $valid; } /** * Check if a coupon is valid. * * @return bool */ public function is_valid_for_cart() { return apply_filters( 'kkart_coupon_is_valid_for_cart', $this->is_type( kkart_get_cart_coupon_types() ), $this ); } /** * Check if a coupon is valid for a product. * * @param KKART_Product $product Product instance. * @param array $values Values. * @return bool */ public function is_valid_for_product( $product, $values = array() ) { if ( ! $this->is_type( kkart_get_product_coupon_types() ) ) { return apply_filters( 'kkart_coupon_is_valid_for_product', false, $product, $this, $values ); } $valid = false; $product_cats = kkart_get_product_cat_ids( $product->is_type( 'variation' ) ? $product->get_parent_id() : $product->get_id() ); $product_ids = array( $product->get_id(), $product->get_parent_id() ); // Specific products get the discount. if ( count( $this->get_product_ids() ) && count( array_intersect( $product_ids, $this->get_product_ids() ) ) ) { $valid = true; } // Category discounts. if ( count( $this->get_product_categories() ) && count( array_intersect( $product_cats, $this->get_product_categories() ) ) ) { $valid = true; } // No product ids - all items discounted. if ( ! count( $this->get_product_ids() ) && ! count( $this->get_product_categories() ) ) { $valid = true; } // Specific product IDs excluded from the discount. if ( count( $this->get_excluded_product_ids() ) && count( array_intersect( $product_ids, $this->get_excluded_product_ids() ) ) ) { $valid = false; } // Specific categories excluded from the discount. if ( count( $this->get_excluded_product_categories() ) && count( array_intersect( $product_cats, $this->get_excluded_product_categories() ) ) ) { $valid = false; } // Sale Items excluded from discount. if ( $this->get_exclude_sale_items() && $product->is_on_sale() ) { $valid = false; } return apply_filters( 'kkart_coupon_is_valid_for_product', $valid, $product, $this, $values ); } /** * Converts one of the KKART_Coupon message/error codes to a message string and. * displays the message/error. * * @param int $msg_code Message/error code. */ public function add_coupon_message( $msg_code ) { $msg = $msg_code < 200 ? $this->get_coupon_error( $msg_code ) : $this->get_coupon_message( $msg_code ); if ( ! $msg ) { return; } if ( $msg_code < 200 ) { kkart_add_notice( $msg, 'error' ); } else { kkart_add_notice( $msg ); } } /** * Map one of the KKART_Coupon message codes to a message string. * * @param integer $msg_code Message code. * @return string Message/error string. */ public function get_coupon_message( $msg_code ) { switch ( $msg_code ) { case self::KKART_COUPON_SUCCESS: $msg = __( 'Coupon code applied successfully.', 'kkart' ); break; case self::KKART_COUPON_REMOVED: $msg = __( 'Coupon code removed successfully.', 'kkart' ); break; default: $msg = ''; break; } return apply_filters( 'kkart_coupon_message', $msg, $msg_code, $this ); } /** * Map one of the KKART_Coupon error codes to a message string. * * @param int $err_code Message/error code. * @return string Message/error string */ public function get_coupon_error( $err_code ) { switch ( $err_code ) { case self::E_KKART_COUPON_INVALID_FILTERED: $err = __( 'Coupon is not valid.', 'kkart' ); break; case self::E_KKART_COUPON_NOT_EXIST: /* translators: %s: coupon code */ $err = sprintf( __( 'Coupon "%s" does not exist!', 'kkart' ), esc_html( $this->get_code() ) ); break; case self::E_KKART_COUPON_INVALID_REMOVED: /* translators: %s: coupon code */ $err = sprintf( __( 'Sorry, it seems the coupon "%s" is invalid - it has now been removed from your order.', 'kkart' ), esc_html( $this->get_code() ) ); break; case self::E_KKART_COUPON_NOT_YOURS_REMOVED: /* translators: %s: coupon code */ $err = sprintf( __( 'Sorry, it seems the coupon "%s" is not yours - it has now been removed from your order.', 'kkart' ), esc_html( $this->get_code() ) ); break; case self::E_KKART_COUPON_ALREADY_APPLIED: $err = __( 'Coupon code already applied!', 'kkart' ); break; case self::E_KKART_COUPON_ALREADY_APPLIED_INDIV_USE_ONLY: /* translators: %s: coupon code */ $err = sprintf( __( 'Sorry, coupon "%s" has already been applied and cannot be used in conjunction with other coupons.', 'kkart' ), esc_html( $this->get_code() ) ); break; case self::E_KKART_COUPON_USAGE_LIMIT_REACHED: $err = __( 'Coupon usage limit has been reached.', 'kkart' ); break; case self::E_KKART_COUPON_EXPIRED: $err = __( 'This coupon has expired.', 'kkart' ); break; case self::E_KKART_COUPON_MIN_SPEND_LIMIT_NOT_MET: /* translators: %s: coupon minimum amount */ $err = sprintf( __( 'The minimum spend for this coupon is %s.', 'kkart' ), kkart_price( $this->get_minimum_amount() ) ); break; case self::E_KKART_COUPON_MAX_SPEND_LIMIT_MET: /* translators: %s: coupon maximum amount */ $err = sprintf( __( 'The maximum spend for this coupon is %s.', 'kkart' ), kkart_price( $this->get_maximum_amount() ) ); break; case self::E_KKART_COUPON_NOT_APPLICABLE: $err = __( 'Sorry, this coupon is not applicable to your cart contents.', 'kkart' ); break; case self::E_KKART_COUPON_EXCLUDED_PRODUCTS: // Store excluded products that are in cart in $products. $products = array(); if ( ! KKART()->cart->is_empty() ) { foreach ( KKART()->cart->get_cart() as $cart_item_key => $cart_item ) { if ( in_array( intval( $cart_item['product_id'] ), $this->get_excluded_product_ids(), true ) || in_array( intval( $cart_item['variation_id'] ), $this->get_excluded_product_ids(), true ) || in_array( intval( $cart_item['data']->get_parent_id() ), $this->get_excluded_product_ids(), true ) ) { $products[] = $cart_item['data']->get_name(); } } } /* translators: %s: products list */ $err = sprintf( __( 'Sorry, this coupon is not applicable to the products: %s.', 'kkart' ), implode( ', ', $products ) ); break; case self::E_KKART_COUPON_EXCLUDED_CATEGORIES: // Store excluded categories that are in cart in $categories. $categories = array(); if ( ! KKART()->cart->is_empty() ) { foreach ( KKART()->cart->get_cart() as $cart_item_key => $cart_item ) { $product_cats = kkart_get_product_cat_ids( $cart_item['product_id'] ); $intersect = array_intersect( $product_cats, $this->get_excluded_product_categories() ); if ( count( $intersect ) > 0 ) { foreach ( $intersect as $cat_id ) { $cat = get_term( $cat_id, 'product_cat' ); $categories[] = $cat->name; } } } } /* translators: %s: categories list */ $err = sprintf( __( 'Sorry, this coupon is not applicable to the categories: %s.', 'kkart' ), implode( ', ', array_unique( $categories ) ) ); break; case self::E_KKART_COUPON_NOT_VALID_SALE_ITEMS: $err = __( 'Sorry, this coupon is not valid for sale items.', 'kkart' ); break; default: $err = ''; break; } return apply_filters( 'kkart_coupon_error', $err, $err_code, $this ); } /** * Map one of the KKART_Coupon error codes to an error string. * No coupon instance will be available where a coupon does not exist, * so this static method exists. * * @param int $err_code Error code. * @return string Error string. */ public static function get_generic_coupon_error( $err_code ) { switch ( $err_code ) { case self::E_KKART_COUPON_NOT_EXIST: $err = __( 'Coupon does not exist!', 'kkart' ); break; case self::E_KKART_COUPON_PLEASE_ENTER: $err = __( 'Please enter a coupon code.', 'kkart' ); break; default: $err = ''; break; } // When using this static method, there is no $this to pass to filter. return apply_filters( 'kkart_coupon_error', $err, $err_code, null ); } } PK!3 /theme-support/class-kkart-twenty-twenty-one.phpnu[ 450, 'single_image_width' => 600, ) ); } /** * Open the Twenty Twenty One wrapper. */ public static function output_content_wrapper() { echo '
    '; echo '
    '; } /** * Close the Twenty Twenty One wrapper. */ public static function output_content_wrapper_end() { echo '
    '; echo '
    '; } /** * Enqueue CSS for this theme. * * @param array $styles Array of registered styles. * @return array */ public static function enqueue_styles( $styles ) { unset( $styles['kkart-general'] ); $styles['kkart-general'] = array( 'src' => str_replace( array( 'http:', 'https:' ), '', KKART()->plugin_url() ) . '/assets/css/twenty-twenty-one.css', 'deps' => '', 'version' => Constants::get_constant( 'KKART_VERSION' ), 'media' => 'all', 'has_rtl' => true, ); return apply_filters( 'kkart_twenty_twenty_one_styles', $styles ); } /** * Enqueue the wp-admin CSS overrides for this theme. */ public static function enqueue_admin_styles() { wp_enqueue_style( 'kkart-twenty-twenty-one-admin', str_replace( array( 'http:', 'https:' ), '', KKART()->plugin_url() ) . '/assets/css/twenty-twenty-one-admin.css', '', Constants::get_constant( 'KKART_VERSION' ), 'all' ); } } KKART_Twenty_Twenty_One::init(); PK!0]O]O.gateways/stripe/class-kkart-gateway-stripe.phpnu[id = 'stripe'; $this->method_title = esc_html__( 'Stripe', 'kkart' ); $this->method_description = esc_html__( 'Stripe redirects you to the Stripe hosted secure payment page.', 'kkart' ); $this->init_form_fields(); $this->init_settings(); // Define user set options $this->title = $this->get_option( 'title', esc_html__( 'Stripe', 'kkart' ) ); $this->description = $this->get_option( 'description', esc_html__( 'Pay via Stripe. Accept Credit Cards, Debit Cards, Alipay and more', 'kkart' ) ); $this->enabled = $this->get_option( 'enabled' ); $this->apiKey = $this->get_option( 'apiKey' ); $this->payment_method = $this->get_option( 'payment_method' ); $this->business_name = $this->get_option( 'business_name' ); $this->webhook = $this->get_option( 'webhook' ); $this->webhook_secret = $this->get_option( 'webhook_secret' ); self::$log_enabled = $this->get_option( 'log_enabled' ); if( $this->webhook ) { add_action( 'kkart_api_kkart_gateway_'. $this->id, array( &$this, 'webhook_response' ) ); } add_action( 'kkart_update_options_payment_gateways_' . $this->id, array( &$this, 'process_admin_options' ) ); add_action( 'admin_notices', array( $this, 'admin_notices' ) ); } public function init_form_fields() { $this->form_fields = array(); $this->form_fields['enabled'] = array( 'title' => esc_html__( 'Enable/Disable', 'kkart' ), 'type' => 'checkbox', 'label' => esc_html__( 'Enable Stripe Payment Gateway', 'kkart' ), 'default' => 'no' ); $this->form_fields['title'] = array( 'title' => esc_html__( 'Title', 'kkart' ), 'type' => 'text', 'description' => esc_html__( 'This controls the title which the user sees during checkout.', 'kkart' ), 'default' => esc_html__( 'Stripe', 'kkart' ), 'desc_tip' => true ); $this->form_fields['description'] = array( 'title' => esc_html__( 'Description', 'kkart' ), 'type' => 'textarea', 'description' => esc_html__( 'This controls the description which the user sees during checkout.', 'kkart' ), 'default' => esc_html__( 'Pay via Stripe. Accept Credit Cards, Debit Cards, Alipay and more', 'kkart' ) ); $this->form_fields['business_name'] = array( 'title' => esc_html__( 'Business Name', 'kkart' ), 'type' => 'text', 'description' => esc_html__( 'This Will Be Shown on Payment page.', 'kkart' ), 'default' => '', ); $this->form_fields['apiKey'] = array( 'title' => esc_html__( 'API Secret Key', 'kkart' ), 'type' => 'password', 'description' => __( 'Please enter the Secret key from
    Stripe Dashboard', 'kkart' ), 'default' => '' ); $this->form_fields['payment_method'] = array( 'title' => esc_html__( 'Payment Method', 'kkart' ), 'type' => 'multiselect', 'class' => 'chosen_select', 'css' => 'width: 350px;', 'options' => array( 'card' => 'Card', 'alipay' => 'AliPay', 'ideal' => 'iDEAL', 'bacs_debit' => 'Bacs Direct Debit', 'bancontact' => 'Bancontact', 'giropay' => 'Giropay', 'p24' => 'Przelewy24', 'eps' => 'EPS', 'sofort' => 'Sofort', 'sepa_debit' => 'SEPA Direct Debit', 'grabpay' => 'GrabPay', 'afterpay_clearpay' => 'Afterpay / Clearpay', 'acss_debit' => 'ACSS Debit', 'wechat_pay' => 'WeChat Pay', 'boleto' => 'Boleto', 'oxxo' => 'OXXO', ), 'default' => array( 'card' ), 'description' => sprintf( __( 'Please make sure the selected gateways are enabled in ', 'kkart' ). 'Stripe Payment Method Settings' ) ); $this->form_fields['log_enabled'] = array( 'title' => esc_html__( 'Logging', 'kkart' ), 'type' => 'checkbox', 'label' => esc_html__( 'Enable Logging', 'kkart' ), 'description' => sprintf( __( 'Log Stripe events, DON\'T ALWAYS ENABLE THIS. You can check this log in %s.', 'kkart' ), '' . esc_html__( 'System Status > Logs', 'kkart' ) . '' ), 'default' => 'no' ); $this->form_fields['webhook_title'] = array( 'title' => esc_html__( 'Webhook Options' ), 'type' => 'title', 'class'=> 'kkart-css-class' ); $this->form_fields['webhook'] = array( 'title' => esc_html__( 'Enable Webhook', 'kkart' ), 'type' => 'checkbox', 'description' => sprintf( __('WebHook URL ','kkart'). add_query_arg( 'kkart-api','KKART_Gateway_Stripe', home_url( '/' ) ).'
    Add Webhook here :- Stripe Webhook' ), 'default' => 'no' ); $this->form_fields['webhook_secret'] = array( 'title' => esc_html__( 'Webhook Secret Key', 'kkart' ), 'type' => 'password', 'description' => esc_html__( 'Webhook secret key is used to authenticate webhooks', 'kkart' ), 'default' => '' ); } public function admin_options() { kkart_enqueue_js(" jQuery( function( $ ) { $('.kkart-css-class').css({'border-top': 'dashed 1px #ccc','padding-top': '15px','width': '68%'}); })" ); parent::admin_options(); } public function process_payment( $order_id ) { $order = kkart_get_order( $order_id ); \Stripe\Stripe::setApiKey( $this->apiKey ); $current_user = wp_get_current_user(); $current_user = (string) $current_user->user_email; $session_data = array( 'customer_email' => $current_user, 'payment_method_types' => $this->payment_method, 'line_items' => [[ 'price_data' => [ 'currency' => get_kkart_currency(), 'product_data' => [ 'name' => $this->business_name ? $this->business_name : get_bloginfo('name'), ], 'unit_amount_decimal' => $this->get_stripe_amount( $order->get_total(), get_kkart_currency() ), ], 'quantity' => 1, ]], 'mode' => 'payment', 'success_url' => esc_url_raw( add_query_arg( 'utm_nooverride', '1', $this->get_return_url( $order ) ) ), 'cancel_url' => $order->get_cancel_order_url(), ); //setting payment_method_options foreach( $this->payment_method as $payment_method ) { if( $this->setPaymentMethodOptions( $payment_method ) ) { $session_data['payment_method_options'] = $this->setPaymentMethodOptions( $payment_method ); } } //setting payment_intent_data if( in_array('bacs_debit', $this->payment_method ) ) { $session_data['payment_intent_data'] = [ 'setup_future_usage' => 'off_session', ]; } $session = \Stripe\Checkout\Session::create( $session_data ); if( isset( $session['id'] ) && isset( $session['url'] ) ) { self::log( '============Payment Initiated ==========', 'debug' ); self::log( $session ); self::log( '========Session Data Ends Here=======', 'debug' ); return array( 'result' => 'success', 'redirect' => $session['url'] ); } self::log( 'Payment Initiation Failed', 'error' ); return array( 'result' => 'failed', //'message' => $['message'] ); } //Processing webhook response public function webhook_response() { if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) || ! isset( $_GET['kkart-api'] ) || ( 'KKART_Gateway_Stripe' !== $_GET['kkart-api'] ) ) { return; } $endpoint_secret = $this->webhook_secret; $payload = @file_get_contents('php://input'); $sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE']; $event = null; try { $event = \Stripe\Webhook::constructEvent( $payload, $sig_header, $endpoint_secret ); } catch(\UnexpectedValueException $e) { // Invalid payload self::log( 'Webhook Source authentication Unexpected Value'. $e ); http_response_code(400); exit(); } catch(\Stripe\Exception\SignatureVerificationException $e) { // Invalid signature self::log( 'Webhook Source authentication failed Invalid Signature'. $e ); http_response_code(400); exit(); } $this->process_webhook( $event ); return; } public function setPaymentMethodOptions( $payment_method ) { switch ( $payment_method ) { case 'wechat_pay': return array( 'wechat_pay' => array( 'client' => "web" ), ); } return; } //Icon to be displayed on checkout page public function get_icon() { $icon_url = untrailingslashit( plugin_dir_url( __FILE__ ) ). '/assets/poweredbystripe.svg' ; $icons_str = sprintf( 'Powered By Stripe', $icon_url ); return apply_filters( 'kkart_gateway_icon', $icons_str, $this->id ); } /** * Get Stripe amount to pay * * @param float $total Amount due. * @param string $currency Accepted currency. * * @return float|int */ public static function get_stripe_amount( $total, $currency = '' ) { if ( ! $currency ) { $currency = get_kkart_currency(); } if ( in_array( strtolower( $currency ), self::no_decimal_currencies() ) ) { return absint( $total ); } else { return absint( kkart_format_decimal( ( (float) $total * 100 ), kkart_get_price_decimals() ) ); // In cents. } } /** * List of currencies supported by Stripe that has no decimals * https://stripe.com/docs/currencies#zero-decimal from https://stripe.com/docs/currencies#presentment-currencies * * @return array $currencies */ public static function no_decimal_currencies() { return ['bif', 'clp', 'djf', 'gnf', 'jpy', 'kmf', 'krw', 'mga', 'pyg', 'rwf', 'ugx', 'vnd', 'vuv', 'xaf', 'xof', 'xpf']; } //Processes the incoming webhook. public function process_webhook( $event ) { $checkout = $event->data->object; switch ( $event->type ) { case 'checkout.session.async_payment_failed': case 'checkout.session.expired': $this->process_webhook_checkout_failed( $checkout ); break; case 'checkout.session.async_payment_succeeded': $this->process_webhook_checkout_succeeded( $checkout ); break; case 'checkout.session.completed': $this->process_webhook_checkout_completed( $checkout ); // ... handle other event types default: self::log( 'Received unknown event type \n' . $event->type, 'warning' ); } } //Parses order_id from success url and returns order using ID public function get_order_by_order_id( $checkout ) { //parses order_id from success url $parsed_url = parse_url( $checkout->success_url ); parse_str( $parsed_url['query'], $param ); $order_id = absint( $param['order_id'] ); $order = kkart_get_order( $order_id ); return $order; } /* * Checkout Succeeded when the payment has been made * but yet to be confirmed from the payment gateway */ public function process_webhook_checkout_succeeded( $checkout ) { $order = $this->get_order_by_order_id( $checkout ); // If order status is already in on-hold status don't continue. if ( $order->has_status( 'on-hold' ) ) { return; } $message = __( 'We are waiting for Payment confirmation from the gateway.', 'kkart' ); self::log( $message ); $order->update_status( 'on-hold', $message ); } //Payment Failed public function process_webhook_checkout_failed( $checkout ) { $order = $this->get_order_by_order_id( $checkout ); // If order status is already in failed status don't continue. if ( $order->has_status( 'failed' ) ) { return; } $message = __( 'This payment failed to clear.', 'kkart' ); self::log( $message ); $order->update_status( 'failed', $message ); } //Payment completion confirmed by thr gateway public function process_webhook_checkout_completed( $checkout ) { $order = $this->get_order_by_order_id( $checkout ); // If order status is already in on-hold status don't continue. if ( $order->has_status( 'processing' ) ) { return; } // Store other data such as fees $order->set_transaction_id( $checkout->id ); $order->payment_complete( $checkout->id ); $order->update_status( 'processing', $message ); self::log( 'Order payment Success Confirmed' ); } public function process_refund( $order_id, $amount = null, $reason = '' ) { $order = kkart_get_order( $order_id ); if ( ! $order or ! $order->get_transaction_id() ) { return new WP_Error('error', __('Refund failed: No transaction ID', 'kkart')); } $paymentId = $order->get_transaction_id(); $stripe = new \Stripe\StripeClient( $this->apiKey ); $refund_data = array( 'charge' => $paymentId, ); //checks if amount is given else the default is full amount of the order if ( $amount ) { $refund_data['amount'] = $this->get_stripe_amount( $amount, get_kkart_currency() ); } if ( !empty( $reason ) ) { $refund_data['reason'] = $reason; } try{ $refund = $stripe->refunds->create( $refund_data ); $order->add_order_note( __( 'Refund Id: ' . $refund->id, 'kkart' ) ); return true; } catch(Exception $e) { self::log( 'Refund Failed' . $e->getMessage() ); return new WP_Error('error', __($e->getMessage(), 'kkart')); } } public function admin_notices() { // If the gateway isn't enabled, don't show it. if ( "no" === $this->enabled ) { return; } $errors = $this->check_requirements(); foreach( $errors as $error ) { if( ! $error ){ continue; } $this->update_option( 'enabled', 'no' ); $error_message = $this->get_error_message( $error ); $this->admin_notice_html( $error_message ); } if( !empty( $this->payment_method ) ) { array_walk( $this->payment_method, array( $this, 'supported_currency' ) ); } } public function get_error_message( $key ) { switch ( $key ) { case 'kkart-gateway-stripe-error-missing-apiKey': return __( 'You forgot to fill your API Key.', 'kkart' ); case 'kkart-gateway-stripe-error-missing-payment-method': return __( 'You forgot to fill your Payment Method.', 'kkart' ); case 'kkart-gateway-stripe-error-missing-business-name': return __( 'You forgot to fill your Business Name.', 'kkart' ); case 'kkart-gateway-stripe-error-missing-webhook-secret': return __( 'You forgot to fill your Webhook Secret.', 'kkart' ); } } public function check_requirements() { $errors = [ empty( $this->get_option( 'apiKey' ) ) ? 'kkart-gateway-stripe-error-missing-apiKey' : null, empty( $this->get_option( 'payment_method' ) ) ? 'kkart-gateway-stripe-error-missing-payment-method' : null, empty( $this->get_option( 'business_name' ) ) ? 'kkart-gateway-stripe-error-missing-business-name' : null, ('yes' === $this->get_option( 'webhook' ) && empty( $this->get_option( 'webhook_secret' ) ) ) ?'kkart-gateway-stripe-error-missing-webhook-secret' : null, ]; return $errors; } // Checks for supported currencies by the payment method public function supported_currency( $gateway, $key ) { if( is_callable( array( $this, 'is_supported_currency_by_'. $gateway ) ) ){ $is_supported = call_user_func( array( $this, 'is_supported_currency_by_'. $gateway ) ); if( $is_supported ) { return; } $gateway_name = str_replace( '_', ' ', ucwords( $gateway, '_' ) ); $this->update_payment_method( $key ); $this->admin_notice_html( $gateway_name . ' does not support the store\'s currency that is ' . get_kkart_currency() ); $this->update_option( 'enabled', 'no' ); } } //Checks if the currency is supported by the gateway public function is_supported_currency( $supported_currencies ) { $store_currency = get_kkart_currency(); if( in_array( $store_currency, $supported_currencies ) ) { return true; } return false; } public function is_supported_currency_by_giropay() { $supported_currencies = [ 'EUR' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_ideal() { $supported_currencies = [ 'EUR' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_p24() { $supported_currencies = [ 'EUR', 'PLN' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_sofort() { $supported_currencies = [ 'EUR' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_eps() { $supported_currencies = [ 'EUR' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_bancontact() { $supported_currencies = [ 'EUR' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_grabpay() { $supported_currencies = [ 'SGD', 'MYR' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_wechat_pay() { $supported_currencies = [ 'CNY', 'AUD', 'CAD', 'EUR', 'GBP', 'HKD', 'JPY', 'SGD', 'USD', 'DKK', 'NOK', 'SEK', 'CHF' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_oxxo() { $supported_currencies = [ 'MXN' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_boleto() { $supported_currencies = [ 'BRL' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_sepa_debit() { $supported_currencies = [ 'EUR' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_bacs_debit() { $supported_currencies = [ 'GBP' ]; return $this->is_supported_currency( $supported_currencies ); } public function is_supported_currency_by_afterpay_clearpay() { $supported_currencies = [ 'USD', 'CAD', 'GBP', 'AUD', 'NZD' ]; return $this->is_supported_currency( $supported_currencies ); } //Updates Payment Method in Stripe public function update_payment_method( $index ) { unset( $this->payment_method[$index] ); $this->payment_method = array_values( $this->payment_method ); $this->update_option( 'payment_method', $this->payment_method ); return; } //Echos Admin Notice HTML public function admin_notice_html( $error ) { echo '

    ' . __( 'To use Stripe as a payment provider, you need to fix the problems below:', 'kkart' ) . '

    ' . '
      ' . $error . '

    '; } public static function log( $message, $level = 'info' ) { if ( self::$log_enabled ) { if ( empty( self::$log ) ) { self::$log = kkart_get_logger(); } self::$log->log( $level, $message, array( 'source' => 'stripe-checkout' ) ); } } } PK!'gateways/stripe/stripe-php/.php_cs.distnu[setRiskyAllowed(true) ->setRules([ // Rulesets '@PSR2' => true, '@PhpCsFixer' => true, '@PhpCsFixer:risky' => true, '@PHP56Migration:risky' => true, '@PHPUnit57Migration:risky' => true, // Additional rules 'fopen_flags' => true, 'linebreak_after_opening_tag' => true, 'native_constant_invocation' => true, 'native_function_invocation' => true, // --- Diffs from @PhpCsFixer / @PhpCsFixer:risky --- // This is the same as the default for the @PhpCsFixer ruleset, minus // the following values: ['include', 'include_once', 'require', // 'require_once']. We could enable them and remove this line after // updating codegen for the `init.php` file to be compliant. 'blank_line_before_statement' => ['statements' => ['break', 'case', 'continue', 'declare', 'default', 'exit', 'goto', 'return', 'switch', 'throw', 'try']], // This is just prettier / easier to read. 'concat_space' => ['spacing' => 'one'], // This causes strange ordering with codegen'd classes. We might be // able to enable this if we update codegen to output class elements // in the correct order. 'ordered_class_elements' => false, // Keep this disabled to avoid unnecessary diffs in PHPDoc comments of // codegen'd classes. 'phpdoc_align' => false, // This is a "risky" rule that causes a bug in our codebase. // Specifically, in `StripeObject.updateAttributes` we construct new // `StripeObject`s for metadata. We can't use `self` there because it // needs to be a raw `StripeObject`. 'self_accessor' => false, ]) ; PK! l(##'gateways/stripe/stripe-php/CHANGELOG.mdnu[# Changelog ## 7.94.0 - 2021-08-19 * [#1173](https://github.com/stripe/stripe-php/pull/1173) API Updates * Add support for new value `fil` on enum `Checkout.Session.locale` * Add support for new value `au_arn` on enum `TaxId.type` ## 7.93.0 - 2021-08-11 * [#1172](https://github.com/stripe/stripe-php/pull/1172) API Updates * Add support for `locale` on `BillingPortal.Session` * [#1171](https://github.com/stripe/stripe-php/pull/1171) Fix typo in docblock `CurlClient::executeStreamingRequestWithRetries` ## 7.92.0 - 2021-07-28 * [#1167](https://github.com/stripe/stripe-php/pull/1167) API Updates * Add support for `account_type` on `BankAccount` * Add support for new value `redacted` on enum `Review.closed_reason` ## 7.91.0 - 2021-07-22 * [#1164](https://github.com/stripe/stripe-php/pull/1164) API Updates * Add support for new values `hr`, `ko`, and `vi` on enum `Checkout.Session.locale` * Add support for `payment_settings` on `Subscription` ## 7.90.0 - 2021-07-20 * [#1163](https://github.com/stripe/stripe-php/pull/1163) API Updates * Add support for `wallet` on `Issuing.Transaction` * [#1160](https://github.com/stripe/stripe-php/pull/1160) Remove unused API error types from docs. ## 7.89.0 - 2021-07-14 * [#1158](https://github.com/stripe/stripe-php/pull/1158) API Updates * Add support for `list_computed_upfront_line_items` method on resource `Quote` * [#1157](https://github.com/stripe/stripe-php/pull/1157) Improve readme for old PHP versions ## 7.88.0 - 2021-07-09 * [#1152](https://github.com/stripe/stripe-php/pull/1152) API Updates * Add support for new resource `Quote` * Add support for `quote` on `Invoice` * Add support for new value `quote_accept` on enum `Invoice.billing_reason` * [#1155](https://github.com/stripe/stripe-php/pull/1155) Add streaming methods to Service infra * Add support for `setStreamingHttpClient` and `streamingHttpClient` to `ApiRequestor` * Add support for `getStreamingClient` and `requestStream` to `AbstractService` * Add support for `requestStream` to `BaseStripeClient` * `\Stripe\RequestOptions::parse` now clones its input if it is already a `RequestOptions` object, to prevent accidental mutation. * [#1151](https://github.com/stripe/stripe-php/pull/1151) Add `mode` constants into Checkout\Session ## 7.87.0 - 2021-06-30 * [#1149](https://github.com/stripe/stripe-php/pull/1149) API Updates * Add support for `wechat_pay` on `PaymentMethod` * [#1143](https://github.com/stripe/stripe-php/pull/1143) Streaming requests * [#1138](https://github.com/stripe/stripe-php/pull/1138) Deprecate travis ## 7.86.0 - 2021-06-25 * [#1145](https://github.com/stripe/stripe-php/pull/1145) API Updates * Add support for `boleto` on `PaymentMethod`. * Add support for `il_vat` as a member of the `TaxID.Type` enum. ## 7.85.0 - 2021-06-18 * [#1142](https://github.com/stripe/stripe-php/pull/1142) API Updates * Add support for new TaxId types: `ca_pst_mb`, `ca_pst_bc`, `ca_gst_hst`, and `ca_pst_sk`. ## 7.84.0 - 2021-06-16 * [#1141](https://github.com/stripe/stripe-php/pull/1141) Update PHPDocs * Add support for `url` on `Checkout\Session` ## 7.83.0 - 2021-06-07 * [#1140](https://github.com/stripe/stripe-php/pull/1140) API Updates * Added support for `tax_id_collection` on `Checkout\Session` and `Checkout\Session#create` * Update `Location` to be expandable on `Terminal\Reader` ## 7.82.0 - 2021-06-04 * [#1136](https://github.com/stripe/stripe-php/pull/1136) Update PHPDocs * Add support for `controller` on `Account`. ## 7.81.0 - 2021-06-04 * [#1135](https://github.com/stripe/stripe-php/pull/1135) API Updates * Add support for new resource `TaxCode` * Add support for `automatic_tax` `Invoice` and`Checkout.Session`. * Add support for `tax_behavior` on `Price` * Add support for `tax_code` on `Product` * Add support for `tax` on `Customer` * Add support for `tax_type` enum on `TaxRate` ## 7.80.0 - 2021-05-26 * [#1130](https://github.com/stripe/stripe-php/pull/1130) Update PHPDocs ## 7.79.0 - 2021-05-19 * [#1126](https://github.com/stripe/stripe-php/pull/1126) API Updates * Added support for new resource `Identity.VerificationReport` * Added support for new resource `Identity.VerificationSession` * `File#list.purpose` and `File.purpose` added new enum members: `identity_document_downloadable` and `selfie`. ## 7.78.0 - 2021-05-05 * [#1120](https://github.com/stripe/stripe-php/pull/1120) Update PHPDocs * Add support for `Radar.EarlyFraudWarning.payment_intent` ## 7.77.0 - 2021-04-12 * [#1110](https://github.com/stripe/stripe-php/pull/1110) Update PHPDocs * Add support for `acss_debit` on `PaymentMethod` * Add support for `payment_method_options` on `Checkout\Session` * [#1107](https://github.com/stripe/stripe-php/pull/1107) Remove duplicate object phpdoc ## 7.76.0 - 2021-03-22 * [#1100](https://github.com/stripe/stripe-php/pull/1100) Update PHPDocs * Added support for `amount_shipping` on `Checkout.Session.total_details` * [#1088](https://github.com/stripe/stripe-php/pull/1088) Make possibility to extend CurlClient ## 7.75.0 - 2021-02-22 * [#1094](https://github.com/stripe/stripe-php/pull/1094) Add support for Billing Portal Configuration API ## 7.74.0 - 2021-02-17 * [#1093](https://github.com/stripe/stripe-php/pull/1093) Update PHPDocs * Add support for on_behalf_of to Invoice ## 7.73.0 - 2021-02-16 * [#1091](https://github.com/stripe/stripe-php/pull/1091) Update PHPDocs * Add support for `afterpay_clearpay` on `PaymentMethod`. ## 7.72.0 - 2021-02-08 * [#1089](https://github.com/stripe/stripe-php/pull/1089) Update PHPDocs * Add support for `afterpay_clearpay_payments` on `Account.capabilities` * Add support for `payment_settings` on `Invoice` ## 7.71.0 - 2021-02-05 * [#1087](https://github.com/stripe/stripe-php/pull/1087) Update PHPDocs * [#1086](https://github.com/stripe/stripe-php/pull/1086) Update CA cert bundle URL ## 7.70.0 - 2021-02-03 * [#1085](https://github.com/stripe/stripe-php/pull/1085) Update PHPDocs * Add support for `nationality` on `Person` * Add member `gb_vat` of `TaxID` enum ## 7.69.0 - 2021-01-21 * [#1079](https://github.com/stripe/stripe-php/pull/1079) Update PHPDocs ## 7.68.0 - 2021-01-14 * [#1063](https://github.com/stripe/stripe-php/pull/1063) Multiple API changes * [#1061](https://github.com/stripe/stripe-php/pull/1061) Bump phpDocumentor to 3.0.0 ## 7.67.0 - 2020-12-09 * [#1060](https://github.com/stripe/stripe-php/pull/1060) Improve PHPDocs for `Discount` * [#1059](https://github.com/stripe/stripe-php/pull/1059) Upgrade PHPStan to 0.12.59 * [#1057](https://github.com/stripe/stripe-php/pull/1057) Bump PHP-CS-Fixer and update code ## 7.66.1 - 2020-12-01 * [#1054](https://github.com/stripe/stripe-php/pull/1054) Improve error message for invalid keys in StripeClient ## 7.66.0 - 2020-11-24 * [#1053](https://github.com/stripe/stripe-php/pull/1053) Update PHPDocs ## 7.65.0 - 2020-11-19 * [#1050](https://github.com/stripe/stripe-php/pull/1050) Added constants for `proration_behavior` on `Subscription` ## 7.64.0 - 2020-11-18 * [#1049](https://github.com/stripe/stripe-php/pull/1049) Update PHPDocs ## 7.63.0 - 2020-11-17 * [#1048](https://github.com/stripe/stripe-php/pull/1048) Update PHPDocs * [#1046](https://github.com/stripe/stripe-php/pull/1046) Force IPv4 resolving ## 7.62.0 - 2020-11-09 * [#1041](https://github.com/stripe/stripe-php/pull/1041) Add missing constants on `Event` * [#1038](https://github.com/stripe/stripe-php/pull/1038) Update PHPDocs ## 7.61.0 - 2020-10-20 * [#1030](https://github.com/stripe/stripe-php/pull/1030) Add support for `jp_rn` and `ru_kpp` as a `type` on `TaxId` ## 7.60.0 - 2020-10-15 * [#1027](https://github.com/stripe/stripe-php/pull/1027) Warn if opts are in params ## 7.58.0 - 2020-10-14 * [#1026](https://github.com/stripe/stripe-php/pull/1026) Add support for the Payout Reverse API ## 7.57.0 - 2020-09-29 * [#1020](https://github.com/stripe/stripe-php/pull/1020) Add support for the `SetupAttempt` resource and List API ## 7.56.0 - 2020-09-25 * [#1019](https://github.com/stripe/stripe-php/pull/1019) Update PHPDocs ## 7.55.0 - 2020-09-24 * [#1018](https://github.com/stripe/stripe-php/pull/1018) Multiple API changes * Updated PHPDocs * Added `TYPE_CONTRIBUTION` as a constant on `BalanceTransaction` ## 7.54.0 - 2020-09-23 * [#1017](https://github.com/stripe/stripe-php/pull/1017) Updated PHPDoc ## 7.53.1 - 2020-09-22 * [#1015](https://github.com/stripe/stripe-php/pull/1015) Bugfix: don't error on systems with php_uname in disablefunctions with whitespace ## 7.53.0 - 2020-09-21 * [#1016](https://github.com/stripe/stripe-php/pull/1016) Updated PHPDocs ## 7.52.0 - 2020-09-08 * [#1010](https://github.com/stripe/stripe-php/pull/1010) Update PHPDocs ## 7.51.0 - 2020-09-02 * [#1007](https://github.com/stripe/stripe-php/pull/1007) Multiple API changes * Add support for the Issuing Dispute Submit API * Add constants for `payment_status` on Checkout `Session` * [#1003](https://github.com/stripe/stripe-php/pull/1003) Add trim to getSignatures to allow for leading whitespace. ## 7.50.0 - 2020-08-28 * [#1005](https://github.com/stripe/stripe-php/pull/1005) Updated PHPDocs ## 7.49.0 - 2020-08-19 * [#998](https://github.com/stripe/stripe-php/pull/998) PHPDocs updated ## 7.48.0 - 2020-08-17 * [#997](https://github.com/stripe/stripe-php/pull/997) PHPDocs updated * [#996](https://github.com/stripe/stripe-php/pull/996) Fixing telemetry ## 7.47.0 - 2020-08-13 * [#994](https://github.com/stripe/stripe-php/pull/994) Nullable balance_transactions on issuing disputes * [#991](https://github.com/stripe/stripe-php/pull/991) Fix invalid return types in OAuthService ## 7.46.1 - 2020-08-07 * [#990](https://github.com/stripe/stripe-php/pull/990) PHPdoc changes ## 7.46.0 - 2020-08-05 * [#989](https://github.com/stripe/stripe-php/pull/989) Add support for the `PromotionCode` resource and APIs ## 7.45.0 - 2020-07-28 * [#981](https://github.com/stripe/stripe-php/pull/981) PHPdoc updates ## 7.44.0 - 2020-07-20 * [#948](https://github.com/stripe/stripe-php/pull/948) Add `first()` and `last()` functions to `Collection` ## 7.43.0 - 2020-07-17 * [#975](https://github.com/stripe/stripe-php/pull/975) Add support for `political_exposure` on `Person` ## 7.42.0 - 2020-07-15 * [#974](https://github.com/stripe/stripe-php/pull/974) Add new constants for `purpose` on `File` ## 7.41.1 - 2020-07-15 * [#973](https://github.com/stripe/stripe-php/pull/973) Multiple PHPDoc fixes ## 7.41.0 - 2020-07-14 * [#971](https://github.com/stripe/stripe-php/pull/971) Adds enum values for `billing_address_collection` on Checkout `Session` ## 7.40.0 - 2020-07-06 * [#964](https://github.com/stripe/stripe-php/pull/964) Add OAuthService ## 7.39.0 - 2020-06-25 * [#960](https://github.com/stripe/stripe-php/pull/960) Add constants for `payment_behavior` on `Subscription` ## 7.38.0 - 2020-06-24 * [#959](https://github.com/stripe/stripe-php/pull/959) Add multiple constants missing for `Event` ## 7.37.2 - 2020-06-23 * [#957](https://github.com/stripe/stripe-php/pull/957) Updated PHPDocs ## 7.37.1 - 2020-06-11 * [#952](https://github.com/stripe/stripe-php/pull/952) Improve PHPDoc ## 7.37.0 - 2020-06-09 * [#950](https://github.com/stripe/stripe-php/pull/950) Add support for `id_npwp` and `my_frp` as `type` on `TaxId` ## 7.36.2 - 2020-06-03 * [#946](https://github.com/stripe/stripe-php/pull/946) Update PHPDoc ## 7.36.1 - 2020-05-28 * [#938](https://github.com/stripe/stripe-php/pull/938) Remove extra array_keys() call. * [#942](https://github.com/stripe/stripe-php/pull/942) fix autopagination for service methods ## 7.36.0 - 2020-05-21 * [#937](https://github.com/stripe/stripe-php/pull/937) Add support for `ae_trn`, `cl_tin` and `sa_vat` as `type` on `TaxId` ## 7.35.0 - 2020-05-20 * [#936](https://github.com/stripe/stripe-php/pull/936) Add `anticipation_repayment` as a `type` on `BalanceTransaction` ## 7.34.0 - 2020-05-18 * [#934](https://github.com/stripe/stripe-php/pull/934) Add support for `issuing_dispute` as a `type` on `BalanceTransaction` ## 7.33.1 - 2020-05-15 * [#933](https://github.com/stripe/stripe-php/pull/933) Services bugfix: convert nested null params to empty strings ## 7.33.0 - 2020-05-14 * [#771](https://github.com/stripe/stripe-php/pull/771) Introduce client/services API. The [migration guide](https://github.com/stripe/stripe-php/wiki/Migration-to-StripeClient-and-services-in-7.33.0) contains before & after examples of the backwards-compatible changes. ## 7.32.1 - 2020-05-13 * [#932](https://github.com/stripe/stripe-php/pull/932) Fix multiple PHPDoc ## 7.32.0 - 2020-05-11 * [#931](https://github.com/stripe/stripe-php/pull/931) Add support for the `LineItem` resource and APIs ## 7.31.0 - 2020-05-01 * [#927](https://github.com/stripe/stripe-php/pull/927) Add support for new tax IDs ## 7.30.0 - 2020-04-29 * [#924](https://github.com/stripe/stripe-php/pull/924) Add support for the `Price` resource and APIs ## 7.29.0 - 2020-04-22 * [#920](https://github.com/stripe/stripe-php/pull/920) Add support for the `Session` resource and APIs on the `BillingPortal` namespace ## 7.28.1 - 2020-04-10 * [#915](https://github.com/stripe/stripe-php/pull/915) Improve PHPdocs for many classes ## 7.28.0 - 2020-04-03 * [#912](https://github.com/stripe/stripe-php/pull/912) Preserve backwards compatibility for typoed `TYPE_ADJUSTEMENT` enum. * [#911](https://github.com/stripe/stripe-php/pull/911) Codegenerated PHPDoc for nested resources * [#902](https://github.com/stripe/stripe-php/pull/902) Update docstrings for nested resources ## 7.27.3 - 2020-03-18 * [#899](https://github.com/stripe/stripe-php/pull/899) Convert keys to strings in `StripeObject::toArray()` ## 7.27.2 - 2020-03-13 * [#894](https://github.com/stripe/stripe-php/pull/894) Multiple PHPDocs changes ## 7.27.1 - 2020-03-03 * [#890](https://github.com/stripe/stripe-php/pull/890) Update PHPdoc ## 7.27.0 - 2020-02-28 * [#889](https://github.com/stripe/stripe-php/pull/889) Add new constants for `type` on `TaxId` ## 7.26.0 - 2020-02-26 * [#886](https://github.com/stripe/stripe-php/pull/886) Add support for listing Checkout `Session` * [#883](https://github.com/stripe/stripe-php/pull/883) Add PHPDoc class descriptions ## 7.25.0 - 2020-02-14 * [#879](https://github.com/stripe/stripe-php/pull/879) Make `\Stripe\Collection` implement `\Countable` * [#875](https://github.com/stripe/stripe-php/pull/875) Last set of PHP-CS-Fixer updates * [#874](https://github.com/stripe/stripe-php/pull/874) Enable php_unit_internal_class rule * [#873](https://github.com/stripe/stripe-php/pull/873) Add support for phpDocumentor in Makefile * [#872](https://github.com/stripe/stripe-php/pull/872) Another batch of PHP-CS-Fixer rule updates * [#871](https://github.com/stripe/stripe-php/pull/871) Fix a few PHPDoc comments * [#870](https://github.com/stripe/stripe-php/pull/870) More PHP-CS-Fixer tweaks ## 7.24.0 - 2020-02-10 * [#862](https://github.com/stripe/stripe-php/pull/862) Better PHPDoc * [#865](https://github.com/stripe/stripe-php/pull/865) Get closer to `@PhpCsFixer` standard ruleset ## 7.23.0 - 2020-02-05 * [#860](https://github.com/stripe/stripe-php/pull/860) Add PHPDoc types for expandable fields * [#858](https://github.com/stripe/stripe-php/pull/858) Use `native_function_invocation` PHPStan rule * [#857](https://github.com/stripe/stripe-php/pull/857) Update PHPDoc on nested resources * [#855](https://github.com/stripe/stripe-php/pull/855) PHPDoc: `StripeObject` -> `ErrorObject` where appropriate * [#837](https://github.com/stripe/stripe-php/pull/837) Autogen diff * [#854](https://github.com/stripe/stripe-php/pull/854) Upgrade PHPStan and fix settings * [#850](https://github.com/stripe/stripe-php/pull/850) Yet more PHPDoc updates ## 7.22.0 - 2020-01-31 * [#849](https://github.com/stripe/stripe-php/pull/849) Add new constants for `type` on `TaxId` * [#843](https://github.com/stripe/stripe-php/pull/843) Even more PHPDoc fixes * [#841](https://github.com/stripe/stripe-php/pull/841) More PHPDoc fixes ## 7.21.1 - 2020-01-29 * [#840](https://github.com/stripe/stripe-php/pull/840) Update phpdocs across multiple resources. ## 7.21.0 - 2020-01-28 * [#839](https://github.com/stripe/stripe-php/pull/839) Add support for `TYPE_ES_CIF` on `TaxId` ## 7.20.0 - 2020-01-23 * [#836](https://github.com/stripe/stripe-php/pull/836) Add new type values for `TaxId` ## 7.19.1 - 2020-01-14 * [#831](https://github.com/stripe/stripe-php/pull/831) Fix incorrect `UnexpectedValueException` instantiation ## 7.19.0 - 2020-01-14 * [#830](https://github.com/stripe/stripe-php/pull/830) Add support for `CreditNoteLineItem` ## 7.18.0 - 2020-01-13 * [#829](https://github.com/stripe/stripe-php/pull/829) Don't call php_uname function if disabled by php.ini ## 7.17.0 - 2020-01-08 * [#821](https://github.com/stripe/stripe-php/pull/821) Improve PHPDoc types for `ApiErrorException.get/setJsonBody()` methods ## 7.16.0 - 2020-01-06 * [#826](https://github.com/stripe/stripe-php/pull/826) Rename remaining `$options` to `$opts` * [#825](https://github.com/stripe/stripe-php/pull/825) Update PHPDoc ## 7.15.0 - 2020-01-06 * [#824](https://github.com/stripe/stripe-php/pull/824) Add constant `TYPE_SG_UEN` to `TaxId` ## 7.14.2 - 2019-12-04 * [#816](https://github.com/stripe/stripe-php/pull/816) Disable autoloader when checking for `Throwable` ## 7.14.1 - 2019-11-26 * [#812](https://github.com/stripe/stripe-php/pull/812) Fix invalid PHPdoc on `Subscription` ## 7.14.0 - 2019-11-26 * [#811](https://github.com/stripe/stripe-php/pull/811) Add support for `CreditNote` preview. ## 7.13.0 - 2019-11-19 * [#808](https://github.com/stripe/stripe-php/pull/808) Add support for listing lines on an Invoice directly via `Invoice::allLines()` ## 7.12.0 - 2019-11-08 - [#805](https://github.com/stripe/stripe-php/pull/805) Add Source::allSourceTransactions and SubscriptionItem::allUsageRecordSummaries - [#798](https://github.com/stripe/stripe-php/pull/798) The argument of `array_key_exists` cannot be `null` - [#803](https://github.com/stripe/stripe-php/pull/803) Removed unwanted got ## 7.11.0 - 2019-11-06 - [#797](https://github.com/stripe/stripe-php/pull/797) Add support for reverse pagination ## 7.10.0 - 2019-11-05 - [#795](https://github.com/stripe/stripe-php/pull/795) Add support for `Mandate` ## 7.9.0 - 2019-11-05 - [#794](https://github.com/stripe/stripe-php/pull/794) Add PHPDoc to `ApiResponse` - [#792](https://github.com/stripe/stripe-php/pull/792) Use single quotes for `OBJECT_NAME` constants ## 7.8.0 - 2019-11-05 - [#790](https://github.com/stripe/stripe-php/pull/790) Mark nullable fields in PHPDoc - [#788](https://github.com/stripe/stripe-php/pull/788) Early codegen fixes - [#787](https://github.com/stripe/stripe-php/pull/787) Use PHPStan in Travis CI ## 7.7.1 - 2019-10-25 - [#781](https://github.com/stripe/stripe-php/pull/781) Fix telemetry header - [#780](https://github.com/stripe/stripe-php/pull/780) Contributor Convenant ## 7.7.0 - 2019-10-23 - [#776](https://github.com/stripe/stripe-php/pull/776) Add `CAPABILITY_TRANSFERS` to `Account` - [#778](https://github.com/stripe/stripe-php/pull/778) Add support for `TYPE_MX_RFC` type on `TaxId` ## 7.6.0 - 2019-10-22 - [#770](https://github.com/stripe/stripe-php/pull/770) Add missing constants for Customer's `TaxId` ## 7.5.0 - 2019-10-18 - [#768](https://github.com/stripe/stripe-php/pull/768) Redact API key in `RequestOptions` debug info ## 7.4.0 - 2019-10-15 - [#764](https://github.com/stripe/stripe-php/pull/764) Add support for HTTP request monitoring callback ## 7.3.1 - 2019-10-07 - [#755](https://github.com/stripe/stripe-php/pull/755) Respect Stripe-Should-Retry and Retry-After headers ## 7.3.0 - 2019-10-02 - [#752](https://github.com/stripe/stripe-php/pull/752) Add `payment_intent.canceled` and `setup_intent.canceled` events - [#749](https://github.com/stripe/stripe-php/pull/749) Call `toArray()` on objects only ## 7.2.2 - 2019-09-24 - [#746](https://github.com/stripe/stripe-php/pull/746) Add missing decline codes ## 7.2.1 - 2019-09-23 - [#744](https://github.com/stripe/stripe-php/pull/744) Added new PHPDoc ## 7.2.0 - 2019-09-17 - [#738](https://github.com/stripe/stripe-php/pull/738) Added missing constants for `SetupIntent` events ## 7.1.1 - 2019-09-16 - [#737](https://github.com/stripe/stripe-php/pull/737) Added new PHPDoc ## 7.1.0 - 2019-09-13 - [#736](https://github.com/stripe/stripe-php/pull/736) Make `CaseInsensitiveArray` countable and traversable ## 7.0.2 - 2019-09-06 - [#729](https://github.com/stripe/stripe-php/pull/729) Fix usage of `SignatureVerificationException` in PHPDoc blocks ## 7.0.1 - 2019-09-05 - [#728](https://github.com/stripe/stripe-php/pull/728) Clean up Collection ## 7.0.0 - 2019-09-03 Major version release. The [migration guide](https://github.com/stripe/stripe-php/wiki/Migration-guide-for-v7) contains a detailed list of backwards-incompatible changes with upgrade instructions. Pull requests included in this release (cf. [#552](https://github.com/stripe/stripe-php/pull/552)) (⚠️ = breaking changes): - ⚠️ Drop support for PHP 5.4 ([#551](https://github.com/stripe/stripe-php/pull/551)) - ⚠️ Drop support for PHP 5.5 ([#554](https://github.com/stripe/stripe-php/pull/554)) - Bump dependencies ([#553](https://github.com/stripe/stripe-php/pull/553)) - Remove `CURLFile` check ([#555](https://github.com/stripe/stripe-php/pull/555)) - Update constant definitions for PHP >= 5.6 ([#556](https://github.com/stripe/stripe-php/pull/556)) - ⚠️ Remove `FileUpload` alias ([#557](https://github.com/stripe/stripe-php/pull/557)) - Remove `curl_reset` check ([#570](https://github.com/stripe/stripe-php/pull/570)) - Use `\Stripe\::class` constant instead of strings ([#643](https://github.com/stripe/stripe-php/pull/643)) - Use `array_column` to flatten params ([#686](https://github.com/stripe/stripe-php/pull/686)) - ⚠️ Remove deprecated methods ([#692](https://github.com/stripe/stripe-php/pull/692)) - ⚠️ Remove `IssuerFraudRecord` ([#696](https://github.com/stripe/stripe-php/pull/696)) - Update constructors of Stripe exception classes ([#559](https://github.com/stripe/stripe-php/pull/559)) - Fix remaining TODOs ([#700](https://github.com/stripe/stripe-php/pull/700)) - Use yield for autopagination ([#703](https://github.com/stripe/stripe-php/pull/703)) - ⚠️ Rename fake magic methods and rewrite array conversion ([#704](https://github.com/stripe/stripe-php/pull/704)) - Add `ErrorObject` to Stripe exceptions ([#705](https://github.com/stripe/stripe-php/pull/705)) - Start using PHP CS Fixer ([#706](https://github.com/stripe/stripe-php/pull/706)) - Update error messages for nested resource operations ([#708](https://github.com/stripe/stripe-php/pull/708)) - Upgrade retry logic ([#707](https://github.com/stripe/stripe-php/pull/707)) - ⚠️ `Collection` improvements / fixes ([#715](https://github.com/stripe/stripe-php/pull/715)) - ⚠️ Modernize exceptions ([#709](https://github.com/stripe/stripe-php/pull/709)) - Add constants for error codes ([#716](https://github.com/stripe/stripe-php/pull/716)) - Update certificate bundle ([#717](https://github.com/stripe/stripe-php/pull/717)) - Retry requests on a 429 that's a lock timeout ([#718](https://github.com/stripe/stripe-php/pull/718)) - Fix `toArray()` calls ([#719](https://github.com/stripe/stripe-php/pull/719)) - Couple of fixes for PHP 7.4 ([#725](https://github.com/stripe/stripe-php/pull/725)) ## 6.43.1 - 2019-08-29 - [#722](https://github.com/stripe/stripe-php/pull/722) Make `LoggerInterface::error` compatible with its PSR-3 counterpart - [#714](https://github.com/stripe/stripe-php/pull/714) Add `pending_setup_intent` property in `Subscription` - [#713](https://github.com/stripe/stripe-php/pull/713) Add typehint to `ApiResponse` - [#712](https://github.com/stripe/stripe-php/pull/712) Fix comment - [#701](https://github.com/stripe/stripe-php/pull/701) Start testing PHP 7.3 ## 6.43.0 - 2019-08-09 - [#694](https://github.com/stripe/stripe-php/pull/694) Add `SubscriptionItem::createUsageRecord` method ## 6.42.0 - 2019-08-09 - [#688](https://github.com/stripe/stripe-php/pull/688) Remove `SubscriptionScheduleRevision` - Note that this is technically a breaking change, however we've chosen to release it as a minor version in light of the fact that this resource and its API methods were virtually unused. ## 6.41.0 - 2019-07-31 - [#683](https://github.com/stripe/stripe-php/pull/683) Move the List Balance History API to `/v1/balance_transactions` ## 6.40.0 - 2019-06-27 - [#675](https://github.com/stripe/stripe-php/pull/675) Add support for `SetupIntent` resource and APIs ## 6.39.2 - 2019-06-26 - [#676](https://github.com/stripe/stripe-php/pull/676) Fix exception message in `CustomerBalanceTransaction::update()` ## 6.39.1 - 2019-06-25 - [#674](https://github.com/stripe/stripe-php/pull/674) Add new constants for `collection_method` on `Invoice` ## 6.39.0 - 2019-06-24 - [#673](https://github.com/stripe/stripe-php/pull/673) Enable request latency telemetry by default ## 6.38.0 - 2019-06-17 - [#649](https://github.com/stripe/stripe-php/pull/649) Add support for `CustomerBalanceTransaction` resource and APIs ## 6.37.2 - 2019-06-17 - [#671](https://github.com/stripe/stripe-php/pull/671) Add new PHPDoc - [#672](https://github.com/stripe/stripe-php/pull/672) Add constants for `submit_type` on Checkout `Session` ## 6.37.1 - 2019-06-14 - [#670](https://github.com/stripe/stripe-php/pull/670) Add new PHPDoc ## 6.37.0 - 2019-05-23 - [#663](https://github.com/stripe/stripe-php/pull/663) Add support for `radar.early_fraud_warning` resource ## 6.36.0 - 2019-05-22 - [#661](https://github.com/stripe/stripe-php/pull/661) Add constants for new TaxId types - [#662](https://github.com/stripe/stripe-php/pull/662) Add constants for BalanceTransaction types ## 6.35.2 - 2019-05-20 - [#655](https://github.com/stripe/stripe-php/pull/655) Add constants for payment intent statuses - [#659](https://github.com/stripe/stripe-php/pull/659) Fix PHPDoc for various nested Account actions - [#660](https://github.com/stripe/stripe-php/pull/660) Fix various PHPDoc ## 6.35.1 - 2019-05-20 - [#658](https://github.com/stripe/stripe-php/pull/658) Use absolute value when checking timestamp tolerance ## 6.35.0 - 2019-05-14 - [#651](https://github.com/stripe/stripe-php/pull/651) Add support for the Capability resource and APIs ## 6.34.6 - 2019-05-13 - [#654](https://github.com/stripe/stripe-php/pull/654) Fix typo in definition of `Event::PAYMENT_METHOD_ATTACHED` constant ## 6.34.5 - 2019-05-06 - [#647](https://github.com/stripe/stripe-php/pull/647) Set the return type to static for more operations ## 6.34.4 - 2019-05-06 - [#650](https://github.com/stripe/stripe-php/pull/650) Add missing constants for Event types ## 6.34.3 - 2019-05-01 - [#644](https://github.com/stripe/stripe-php/pull/644) Update return type to `static` to improve static analysis - [#645](https://github.com/stripe/stripe-php/pull/645) Fix constant for `payment_intent.payment_failed` ## 6.34.2 - 2019-04-26 - [#642](https://github.com/stripe/stripe-php/pull/642) Fix an issue where existing idempotency keys would be overwritten when using automatic retries ## 6.34.1 - 2019-04-25 - [#640](https://github.com/stripe/stripe-php/pull/640) Add missing phpdocs ## 6.34.0 - 2019-04-24 - [#626](https://github.com/stripe/stripe-php/pull/626) Add support for the `TaxRate` resource and APIs - [#639](https://github.com/stripe/stripe-php/pull/639) Fix multiple phpdoc issues ## 6.33.0 - 2019-04-22 - [#630](https://github.com/stripe/stripe-php/pull/630) Add support for the `TaxId` resource and APIs ## 6.32.1 - 2019-04-19 - [#636](https://github.com/stripe/stripe-php/pull/636) Correct type of `$personId` in PHPDoc ## 6.32.0 - 2019-04-18 - [#621](https://github.com/stripe/stripe-php/pull/621) Add support for `CreditNote` ## 6.31.5 - 2019-04-12 - [#628](https://github.com/stripe/stripe-php/pull/628) Add constants for `person.*` event types - [#628](https://github.com/stripe/stripe-php/pull/628) Add missing constants for `Account` and `Person` ## 6.31.4 - 2019-04-05 - [#624](https://github.com/stripe/stripe-php/pull/624) Fix encoding of nested parameters in multipart requests ## 6.31.3 - 2019-04-02 - [#623](https://github.com/stripe/stripe-php/pull/623) Only use HTTP/2 with curl >= 7.60.0 ## 6.31.2 - 2019-03-25 - [#619](https://github.com/stripe/stripe-php/pull/619) Fix PHPDoc return types for list methods for nested resources ## 6.31.1 - 2019-03-22 - [#612](https://github.com/stripe/stripe-php/pull/612) Add a lot of constants - [#614](https://github.com/stripe/stripe-php/pull/614) Add missing subscription status constants ## 6.31.0 - 2019-03-18 - [#600](https://github.com/stripe/stripe-php/pull/600) Add support for the `PaymentMethod` resource and APIs - [#606](https://github.com/stripe/stripe-php/pull/606) Add support for retrieving a Checkout `Session` - [#611](https://github.com/stripe/stripe-php/pull/611) Add support for deleting a Terminal `Location` and `Reader` ## 6.30.5 - 2019-03-11 - [#607](https://github.com/stripe/stripe-php/pull/607) Correctly handle case where a metadata key is called `metadata` ## 6.30.4 - 2019-02-27 - [#602](https://github.com/stripe/stripe-php/pull/602) Add `subscription_schedule` to `Subscription` for PHPDoc. ## 6.30.3 - 2019-02-26 - [#603](https://github.com/stripe/stripe-php/pull/603) Improve PHPDoc on the `Source` object to cover all types of Sources currently supported. ## 6.30.2 - 2019-02-25 - [#601](https://github.com/stripe/stripe-php/pull/601) Fix PHPDoc across multiple resources and add support for new events. ## 6.30.1 - 2019-02-16 - [#599](https://github.com/stripe/stripe-php/pull/599) Fix PHPDoc for `SubscriptionSchedule` and `SubscriptionScheduleRevision` ## 6.30.0 - 2019-02-12 - [#590](https://github.com/stripe/stripe-php/pull/590) Add support for `SubscriptionSchedule` and `SubscriptionScheduleRevision` ## 6.29.3 - 2019-01-31 - [#592](https://github.com/stripe/stripe-php/pull/592) Some more PHPDoc fixes ## 6.29.2 - 2019-01-31 - [#591](https://github.com/stripe/stripe-php/pull/591) Fix PHPDoc for nested resources ## 6.29.1 - 2019-01-25 - [#566](https://github.com/stripe/stripe-php/pull/566) Fix dangling message contents - [#586](https://github.com/stripe/stripe-php/pull/586) Don't overwrite `CURLOPT_HTTP_VERSION` option ## 6.29.0 - 2019-01-23 - [#579](https://github.com/stripe/stripe-php/pull/579) Rename `CheckoutSession` to `Session` and move it under the `Checkout` namespace. This is a breaking change, but we've reached out to affected merchants and all new merchants would use the new approach. ## 6.28.1 - 2019-01-21 - [#580](https://github.com/stripe/stripe-php/pull/580) Properly serialize `individual` on `Account` objects ## 6.28.0 - 2019-01-03 - [#576](https://github.com/stripe/stripe-php/pull/576) Add support for iterating directly over `Collection` instances ## 6.27.0 - 2018-12-21 - [#571](https://github.com/stripe/stripe-php/pull/571) Add support for the `CheckoutSession` resource ## 6.26.0 - 2018-12-11 - [#568](https://github.com/stripe/stripe-php/pull/568) Enable persistent connections ## 6.25.0 - 2018-12-10 - [#567](https://github.com/stripe/stripe-php/pull/567) Add support for account links ## 6.24.0 - 2018-11-28 - [#562](https://github.com/stripe/stripe-php/pull/562) Add support for the Review resource - [#564](https://github.com/stripe/stripe-php/pull/564) Add event name constants for subscription schedule aborted/expiring ## 6.23.0 - 2018-11-27 - [#542](https://github.com/stripe/stripe-php/pull/542) Add support for `ValueList` and `ValueListItem` for Radar ## 6.22.1 - 2018-11-20 - [#561](https://github.com/stripe/stripe-php/pull/561) Add cast and some docs to telemetry introduced in 6.22.0/549 ## 6.22.0 - 2018-11-15 - [#549](https://github.com/stripe/stripe-php/pull/549) Add support for client telemetry ## 6.21.1 - 2018-11-12 - [#548](https://github.com/stripe/stripe-php/pull/548) Don't mutate `Exception` class properties from `OAuthBase` error ## 6.21.0 - 2018-11-08 - [#537](https://github.com/stripe/stripe-php/pull/537) Add new API endpoints for the `Invoice` resource. ## 6.20.1 - 2018-11-07 - [#546](https://github.com/stripe/stripe-php/pull/546) Drop files from the Composer package that aren't needed in the release ## 6.20.0 - 2018-10-30 - [#536](https://github.com/stripe/stripe-php/pull/536) Add support for the `Person` resource - [#541](https://github.com/stripe/stripe-php/pull/541) Add support for the `WebhookEndpoint` resource ## 6.19.5 - 2018-10-17 - [#539](https://github.com/stripe/stripe-php/pull/539) Fix methods on `\Stripe\PaymentIntent` to properly pass arguments to the API. ## 6.19.4 - 2018-10-11 - [#534](https://github.com/stripe/stripe-php/pull/534) Fix PSR-4 autoloading for `\Stripe\FileUpload` class alias ## 6.19.3 - 2018-10-09 - [#530](https://github.com/stripe/stripe-php/pull/530) Add constants for `flow` (`FLOW_*`), `status` (`STATUS_*`) and `usage` (`USAGE_*`) on `\Stripe\Source` ## 6.19.2 - 2018-10-08 - [#531](https://github.com/stripe/stripe-php/pull/531) Store HTTP response headers in case-insensitive array ## 6.19.1 - 2018-09-25 - [#526](https://github.com/stripe/stripe-php/pull/526) Ignore null values in request parameters ## 6.19.0 - 2018-09-24 - [#523](https://github.com/stripe/stripe-php/pull/523) Add support for Stripe Terminal ## 6.18.0 - 2018-09-24 - [#520](https://github.com/stripe/stripe-php/pull/520) Rename `\Stripe\FileUpload` to `\Stripe\File` ## 6.17.2 - 2018-09-18 - [#522](https://github.com/stripe/stripe-php/pull/522) Fix warning when adding a new additional owner to an existing array ## 6.17.1 - 2018-09-14 - [#517](https://github.com/stripe/stripe-php/pull/517) Integer-index encode all sequential arrays ## 6.17.0 - 2018-09-05 - [#514](https://github.com/stripe/stripe-php/pull/514) Add support for reporting resources ## 6.16.0 - 2018-08-23 - [#509](https://github.com/stripe/stripe-php/pull/509) Add support for usage record summaries ## 6.15.0 - 2018-08-03 - [#504](https://github.com/stripe/stripe-php/pull/504) Add cancel support for topups ## 6.14.0 - 2018-08-02 - [#505](https://github.com/stripe/stripe-php/pull/505) Add support for file links ## 6.13.0 - 2018-07-31 - [#502](https://github.com/stripe/stripe-php/pull/502) Add `isDeleted()` method to `\Stripe\StripeObject` ## 6.12.0 - 2018-07-28 - [#501](https://github.com/stripe/stripe-php/pull/501) Add support for scheduled query runs (`\Stripe\Sigma\ScheduledQueryRun`) for Sigma ## 6.11.0 - 2018-07-26 - [#500](https://github.com/stripe/stripe-php/pull/500) Add support for Stripe Issuing ## 6.10.4 - 2018-07-19 - [#498](https://github.com/stripe/stripe-php/pull/498) Internal improvements to the `\Stripe\ApiResource.classUrl()` method ## 6.10.3 - 2018-07-16 - [#497](https://github.com/stripe/stripe-php/pull/497) Use HTTP/2 only for HTTPS requests ## 6.10.2 - 2018-07-11 - [#494](https://github.com/stripe/stripe-php/pull/494) Enable HTTP/2 support ## 6.10.1 - 2018-07-10 - [#493](https://github.com/stripe/stripe-php/pull/493) Add PHPDoc for `auto_advance` on `\Stripe\Invoice` ## 6.10.0 - 2018-06-28 - [#488](https://github.com/stripe/stripe-php/pull/488) Add support for `$appPartnerId` to `Stripe::setAppInfo()` ## 6.9.0 - 2018-06-28 - [#487](https://github.com/stripe/stripe-php/pull/487) Add support for payment intents ## 6.8.2 - 2018-06-24 - [#486](https://github.com/stripe/stripe-php/pull/486) Make `Account.deauthorize()` return the `StripeObject` from the API ## 6.8.1 - 2018-06-13 - [#472](https://github.com/stripe/stripe-php/pull/472) Added phpDoc for `ApiRequestor` and others, especially regarding thrown errors ## 6.8.0 - 2018-06-13 - [#481](https://github.com/stripe/stripe-php/pull/481) Add new `\Stripe\Discount` and `\Stripe\OrderItem` classes, add more PHPDoc describing object attributes ## 6.7.4 - 2018-05-29 - [#480](https://github.com/stripe/stripe-php/pull/480) PHPDoc changes for API version 2018-05-21 and the addition of the new `CHARGE_EXPIRED` event type ## 6.7.3 - 2018-05-28 - [#479](https://github.com/stripe/stripe-php/pull/479) Fix unnecessary traits on `\Stripe\InvoiceLineItem` ## 6.7.2 - 2018-05-28 - [#471](https://github.com/stripe/stripe-php/pull/471) Add `OBJECT_NAME` constant to all API resource classes, add `\Stripe\InvoiceLineItem` class ## 6.7.1 - 2018-05-13 - [#468](https://github.com/stripe/stripe-php/pull/468) Update fields in PHP docs for accuracy ## 6.7.0 - 2018-05-09 - [#466](https://github.com/stripe/stripe-php/pull/466) Add support for issuer fraud records ## 6.6.0 - 2018-04-11 - [#460](https://github.com/stripe/stripe-php/pull/460) Add support for flexible billing primitives ## 6.5.0 - 2018-04-05 - [#461](https://github.com/stripe/stripe-php/pull/461) Don't zero keys on non-`metadata` subobjects ## 6.4.2 - 2018-03-17 - [#458](https://github.com/stripe/stripe-php/pull/458) Add PHPDoc for `account` on `\Stripe\Event` ## 6.4.1 - 2018-03-02 - [#455](https://github.com/stripe/stripe-php/pull/455) Fix namespaces in PHPDoc - [#456](https://github.com/stripe/stripe-php/pull/456) Fix namespaces for some exceptions ## 6.4.0 - 2018-02-28 - [#453](https://github.com/stripe/stripe-php/pull/453) Add constants for `reason` (`REASON_*`) and `status` (`STATUS_*`) on `\Stripe\Dispute` ## 6.3.2 - 2018-02-27 - [#452](https://github.com/stripe/stripe-php/pull/452) Add PHPDoc for `amount_paid` and `amount_remaining` on `\Stripe\Invoice` ## 6.3.1 - 2018-02-26 - [#443](https://github.com/stripe/stripe-php/pull/443) Add event types as constants to `\Stripe\Event` class ## 6.3.0 - 2018-02-23 - [#450](https://github.com/stripe/stripe-php/pull/450) Add support for `code` attribute on all Stripe exceptions ## 6.2.0 - 2018-02-21 - [#440](https://github.com/stripe/stripe-php/pull/440) Add support for topups - [#442](https://github.com/stripe/stripe-php/pull/442) Fix PHPDoc for `\Stripe\Error\SignatureVerification` ## 6.1.0 - 2018-02-12 - [#435](https://github.com/stripe/stripe-php/pull/435) Fix header persistence on `Collection` objects - [#436](https://github.com/stripe/stripe-php/pull/436) Introduce new `Idempotency` error class ## 6.0.0 - 2018-02-07 Major version release. List of backwards incompatible changes to watch out for: - The minimum PHP version is now 5.4.0. If you're using PHP 5.3 or older, consider upgrading to a more recent version. * `\Stripe\AttachedObject` no longer exists. Attributes that used to be instances of `\Stripe\AttachedObject` (such as `metadata`) are now instances of `\Stripe\StripeObject`. - Attributes that used to be PHP arrays (such as `legal_entity->additional_owners` on `\Stripe\Account` instances) are now instances of `\Stripe\StripeObject`, except when they are empty. `\Stripe\StripeObject` has array semantics so this should not be an issue unless you are actively checking types. * `\Stripe\Collection` now derives from `\Stripe\StripeObject` rather than from `\Stripe\ApiResource`. Pull requests included in this release: - [#410](https://github.com/stripe/stripe-php/pull/410) Drop support for PHP 5.3 - [#411](https://github.com/stripe/stripe-php/pull/411) Use traits for common API operations - [#414](https://github.com/stripe/stripe-php/pull/414) Use short array syntax - [#404](https://github.com/stripe/stripe-php/pull/404) Fix serialization logic - [#417](https://github.com/stripe/stripe-php/pull/417) Remove `ExternalAccount` class - [#418](https://github.com/stripe/stripe-php/pull/418) Increase test coverage - [#421](https://github.com/stripe/stripe-php/pull/421) Update CA bundle and add script for future updates - [#422](https://github.com/stripe/stripe-php/pull/422) Use vendored CA bundle for all requests - [#428](https://github.com/stripe/stripe-php/pull/428) Support for automatic request retries ## 5.9.2 - 2018-02-07 - [#431](https://github.com/stripe/stripe-php/pull/431) Update PHPDoc @property tags for latest API version ## 5.9.1 - 2018-02-06 - [#427](https://github.com/stripe/stripe-php/pull/427) Add and update PHPDoc @property tags on all API resources ## 5.9.0 - 2018-01-17 - [#421](https://github.com/stripe/stripe-php/pull/421) Updated bundled CA certificates - [#423](https://github.com/stripe/stripe-php/pull/423) Escape unsanitized input in OAuth example ## 5.8.0 - 2017-12-20 - [#403](https://github.com/stripe/stripe-php/pull/403) Add `__debugInfo()` magic method to `StripeObject` ## 5.7.0 - 2017-11-28 - [#390](https://github.com/stripe/stripe-php/pull/390) Remove some unsupported API methods - [#391](https://github.com/stripe/stripe-php/pull/391) Alphabetize the list of API resources in `Util::convertToStripeObject()` and add missing resources - [#393](https://github.com/stripe/stripe-php/pull/393) Fix expiry date update for card sources ## 5.6.0 - 2017-10-31 - [#386](https://github.com/stripe/stripe-php/pull/386) Support for exchange rates APIs ## 5.5.1 - 2017-10-30 - [#387](https://github.com/stripe/stripe-php/pull/387) Allow `personal_address_kana` and `personal_address_kanji` to be updated on an account ## 5.5.0 - 2017-10-27 - [#385](https://github.com/stripe/stripe-php/pull/385) Support for listing source transactions ## 5.4.0 - 2017-10-24 - [#383](https://github.com/stripe/stripe-php/pull/383) Add static methods to manipulate resources from parent - `Account` gains methods for external accounts and login links (e.g. `createExternalAccount`, `createLoginLink`) - `ApplicationFee` gains methods for refunds - `Customer` gains methods for sources - `Transfer` gains methods for reversals ## 5.3.0 - 2017-10-11 - [#378](https://github.com/stripe/stripe-php/pull/378) Rename source `delete` to `detach` (and deprecate the former) ## 5.2.3 - 2017-09-27 - Add PHPDoc for `Card` ## 5.2.2 - 2017-09-20 - Fix deserialization mapping of `FileUpload` objects ## 5.2.1 - 2017-09-14 - Serialized `shipping` nested attribute ## 5.2.0 - 2017-08-29 - Add support for `InvalidClient` OAuth error ## 5.1.3 - 2017-08-14 - Allow `address_kana` and `address_kanji` to be updated for custom accounts ## 5.1.2 - 2017-08-01 - Fix documented return type of `autoPagingIterator()` (was missing namespace) ## 5.1.1 - 2017-07-03 - Fix order returns to use the right URL `/v1/order_returns` ## 5.1.0 - 2017-06-30 - Add support for OAuth ## 5.0.0 - 2017-06-27 - `pay` on invoice now takes params as well as opts ## 4.13.0 - 2017-06-19 - Add support for ephemeral keys ## 4.12.0 - 2017-06-05 - Clients can implement `getUserAgentInfo()` to add additional user agent information ## 4.11.0 - 2017-06-05 - Implement `Countable` for `AttachedObject` (`metadata` and `additional_owners`) ## 4.10.0 - 2017-05-25 - Add support for login links ## 4.9.1 - 2017-05-10 - Fix docs to include arrays on `$id` parameter for retrieve methods ## 4.9.0 - 2017-04-28 - Support for checking webhook signatures ## 4.8.1 - 2017-04-24 - Allow nested field `payout_schedule` to be updated ## 4.8.0 - 2017-04-20 - Add `\Stripe\Stripe::setLogger()` to support an external PSR-3 compatible logger ## 4.7.0 - 2017-04-10 - Add support for payouts and recipient transfers ## 4.6.0 - 2017-04-06 - Please see 4.7.0 instead (no-op release) ## 4.5.1 - 2017-03-22 - Remove hard dependency on cURL ## 4.5.0 - 2017-03-20 - Support for detaching sources from customers ## 4.4.2 - 2017-02-27 - Correct handling of `owner` parameter when updating sources ## 4.4.1 - 2017-02-24 - Correct the error check on a bad JSON decoding ## 4.4.0 - 2017-01-18 - Add support for updating sources ## 4.3.0 - 2016-11-30 - Add support for verifying sources ## 4.2.0 - 2016-11-21 - Add retrieve method for 3-D Secure resources ## 4.1.1 - 2016-10-21 - Add docblock with model properties for `Plan` ## 4.1.0 - 2016-10-18 - Support for 403 status codes (permission denied) ## 4.0.1 - 2016-10-17 - Fix transfer reversal materialization - Fixes for some property definitions in docblocks ## 4.0.0 - 2016-09-28 - Support for subscription items - Drop attempt to force TLS 1.2: please note that this could be breaking if you're using old OS distributions or packages and upgraded recently (so please make sure to test your integration!) ## 3.23.0 - 2016-09-15 - Add support for Apple Pay domains ## 3.22.0 - 2016-09-13 - Add `Stripe::setAppInfo` to allow plugins to register user agent information ## 3.21.0 - 2016-08-25 - Add `Source` model for generic payment sources ## 3.20.0 - 2016-08-08 - Add `getDeclineCode` to card errors ## 3.19.0 - 2016-07-29 - Opt requests directly into TLS 1.2 where OpenSSL >= 1.0.1 (see #277 for context) ## 3.18.0 - 2016-07-28 - Add new `STATUS_` constants for subscriptions ## 3.17.1 - 2016-07-28 - Fix auto-paging iterator so that it plays nicely with `iterator_to_array` ## 3.17.0 - 2016-07-14 - Add field annotations to model classes for better editor hinting ## 3.16.0 - 2016-07-12 - Add `ThreeDSecure` model for 3-D secure payments ## 3.15.0 - 2016-06-29 - Add static `update` method to all resources that can be changed. ## 3.14.3 - 2016-06-20 - Make sure that cURL never sends `Expects: 100-continue`, even on large request bodies ## 3.14.2 - 2016-06-03 - Add `inventory` under `SKU` to list of keys that have nested data and can be updated ## 3.14.1 - 2016-05-27 - Fix some inconsistencies in PHPDoc ## 3.14.0 - 2016-05-25 - Add support for returning Relay orders ## 3.13.0 - 2016-05-04 - Add `list`, `create`, `update`, `retrieve`, and `delete` methods to the Subscription class ## 3.12.1 - 2016-04-07 - Additional check on value arrays for some extra safety ## 3.12.0 - 2016-03-31 - Fix bug `refreshFrom` on `StripeObject` would not take an `$opts` array - Fix bug where `$opts` not passed to parent `save` method in `Account` - Fix bug where non-existent variable was referenced in `reverse` in `Transfer` - Update CA cert bundle for compatibility with OpenSSL versions below 1.0.1 ## 3.11.0 - 2016-03-22 - Allow `CurlClient` to be initialized with default `CURLOPT_*` options ## 3.10.1 - 2016-03-22 - Fix bug where request params and options were ignored in `ApplicationFee`'s `refund.` ## 3.10.0 - 2016-03-15 - Add `reject` on `Account` to support the new API feature ## 3.9.2 - 2016-03-04 - Fix error when an object's metadata is set more than once ## 3.9.1 - 2016-02-24 - Fix encoding behavior of nested arrays for requests (see #227) ## 3.9.0 - 2016-02-09 - Add automatic pagination mechanism with `autoPagingIterator()` - Allow global account ID to be set with `Stripe::setAccountId()` ## 3.8.0 - 2016-02-08 - Add `CountrySpec` model for looking up country payment information ## 3.7.1 - 2016-02-01 - Update bundled CA certs ## 3.7.0 - 2016-01-27 - Support deleting Relay products and SKUs ## 3.6.0 - 2016-01-05 - Allow configuration of HTTP client timeouts ## 3.5.0 - 2015-12-01 - Add a verification routine for external accounts ## 3.4.0 - 2015-09-14 - Products, SKUs, and Orders -- https://stripe.com/relay ## 3.3.0 - 2015-09-11 - Add support for 429 Rate Limit response ## 3.2.0 - 2015-08-17 - Add refund listing and retrieval without an associated charge ## 3.1.0 - 2015-08-03 - Add dispute listing and retrieval - Add support for manage account deletion ## 3.0.0 - 2015-07-28 - Rename `\Stripe\Object` to `\Stripe\StripeObject` (PHP 7 compatibility) - Rename `getCode` and `getParam` in exceptions to `getStripeCode` and `getStripeParam` - Add support for calling `json_encode` on Stripe objects in PHP 5.4+ - Start supporting/testing PHP 7 ## 2.3.0 - 2015-07-06 - Add request ID to all Stripe exceptions ## 2.2.0 - 2015-06-01 - Add support for Alipay accounts as sources - Add support for bank accounts as sources (private beta) - Add support for bank accounts and cards as external_accounts on Account objects ## 2.1.4 - 2015-05-13 - Fix CA certificate file path (thanks @lphilps & @matthewarkin) ## 2.1.3 - 2015-05-12 - Fix to account updating to permit `tos_acceptance` and `personal_address` to be set properly - Fix to Transfer reversal creation (thanks @neatness!) - Network requests are now done through a swappable class for easier mocking ## 2.1.2 - 2015-04-10 - Remove SSL cert revokation checking (all pre-Heartbleed certs have expired) - Bug fixes to account updating ## 2.1.1 - 2015-02-27 - Support transfer reversals ## 2.1.0 - 2015-02-19 - Support new API version (2015-02-18) - Added Bitcoin Receiever update and delete actions - Edited tests to prefer "source" over "card" as per new API version ## 2.0.1 - 2015-02-16 - Fix to fetching endpoints that use a non-default baseUrl (`FileUpload`) ## 2.0.0 - 2015-02-14 - Bumped minimum version to 5.3.3 - Switched to Stripe namespace instead of Stripe\_ class name prefiexes (thanks @chadicus!) - Switched tests to PHPUnit (thanks @chadicus!) - Switched style guide to PSR2 (thanks @chadicus!) - Added \$opts hash to the end of most methods: this permits passing 'idempotency_key', 'stripe_account', or 'stripe_version'. The last 2 will persist across multiple object loads. - Added support for retrieving Account by ID ## 1.18.0 - 2015-01-21 - Support making bitcoin charges through BitcoinReceiver source object ## 1.17.5 - 2014-12-23 - Adding support for creating file uploads. ## 1.17.4 - 2014-12-15 - Saving objects fetched with a custom key now works (thanks @JustinHook & @jpasilan) - Added methods for reporting charges as safe or fraudulent and for specifying the reason for refunds ## 1.17.3 - 2014-11-06 - Better handling of HHVM support for SSL certificate blacklist checking. ## 1.17.2 - 2014-09-23 - Coupons now are backed by a `Stripe_Coupon` instead of `Stripe_Object`, and support updating metadata - Running operations (`create`, `retrieve`, `all`) on upcoming invoice items now works ## 1.17.1 - 2014-07-31 - Requests now send Content-Type header ## 1.17.0 - 2014-07-29 - Application Fee refunds now a list instead of array - HHVM now works - Small bug fixes (thanks @bencromwell & @fastest963) - `__toString` now returns the name of the object in addition to its JSON representation ## 1.16.0 - 2014-06-17 - Add metadata for refunds and disputes ## 1.15.0 - 2014-05-28 - Support canceling transfers ## 1.14.1 - 2014-05-21 - Support cards for recipients. ## 1.13.1 - 2014-05-15 - Fix bug in account resource where `id` wasn't in the result ## 1.13.0 - 2014-04-10 - Add support for certificate blacklisting - Update ca bundle - Drop support for HHVM (Temporarily) ## 1.12.0 - 2014-04-01 - Add Stripe_RateLimitError for catching rate limit errors. - Update to Zend coding style (thanks, @jpiasetz) ## 1.11.0 - 2014-01-29 - Add support for multiple subscriptions per customer ## 1.10.1 - 2013-12-02 - Add new ApplicationFee ## 1.9.1 - 2013-11-08 - Fix a bug where a null nestable object causes warnings to fire. ## 1.9.0 - 2013-10-16 - Add support for metadata API. ## 1.8.4 - 2013-09-18 - Add support for closing disputes. ## 1.8.3 - 2013-08-13 - Add new Balance and BalanceTransaction ## 1.8.2 - 2013-08-12 - Add support for unsetting attributes by updating to NULL. Setting properties to a blank string is now an error. ## 1.8.1 - 2013-07-12 - Add support for multiple cards API (Stripe API version 2013-07-12: https://stripe.com/docs/upgrades#2013-07-05) ## 1.8.0 - 2013-04-11 - Allow Transfers to be creatable - Add new Recipient resource ## 1.7.15 - 2013-02-21 - Add 'id' to the list of permanent object attributes ## 1.7.14 - 2013-02-20 - Don't re-encode strings that are already encoded in UTF-8. If you were previously using plan or coupon objects with UTF-8 IDs, they may have been treated as ISO-8859-1 (Latin-1) and encoded to UTF-8 a 2nd time. You may now need to pass the IDs to utf8_encode before passing them to Stripe_Plan::retrieve or Stripe_Coupon::retrieve. - Ensure that all input is encoded in UTF-8 before submitting it to Stripe's servers. (github issue #27) ## 1.7.13 - 2013-02-01 - Add support for passing options when retrieving Stripe objects e.g., Stripe_Charge::retrieve(array("id"=>"foo", "expand" => array("customer"))); Stripe_Charge::retrieve("foo") will continue to work ## 1.7.12 - 2013-01-15 - Add support for setting a Stripe API version override ## 1.7.11 - 2012-12-30 - Version bump to cleanup constants and such (fix issue #26) ## 1.7.10 - 2012-11-08 - Add support for updating charge disputes. - Fix bug preventing retrieval of null attributes ## 1.7.9 - 2012-11-08 - Fix usage under autoloaders such as the one generated by composer (fix issue #22) ## 1.7.8 - 2012-10-30 - Add support for creating invoices. - Add support for new invoice lines return format - Add support for new list objects ## 1.7.7 - 2012-09-14 - Get all of the various version numbers in the repo in sync (no other changes) ## 1.7.6 - 2012-08-31 - Add update and pay methods to Invoice resource ## 1.7.5 - 2012-08-23 - Change internal function names so that Stripe_SingletonApiRequest is E_STRICT-clean (github issue #16) ## 1.7.4 - 2012-08-21 - Bugfix so that Stripe objects (e.g. Customer, Charge objects) used in API calls are transparently converted to their object IDs ## 1.7.3 - 2012-08-15 - Add new Account resource ## 1.7.2 - 2012-06-26 - Make clearer that you should be including lib/Stripe.php, not test/Stripe.php (github issue #14) ## 1.7.1 - 2012-05-24 - Add missing argument to Stripe_InvalidRequestError constructor in Stripe_ApiResource::instanceUrl. Fixes a warning when Stripe_ApiResource::instanceUrl is called on a resource with no ID (fix issue #12) ## 1.7.0 - 2012-05-17 - Support Composer and Packagist (github issue #9) - Add new deleteDiscount method to Stripe_Customer - Add new Transfer resource - Switch from using HTTP Basic auth to Bearer auth. (Note: Stripe will support Basic auth for the indefinite future, but recommends Bearer auth when possible going forward) - Numerous test suite improvements PK!J.ⱀ$gateways/stripe/stripe-php/build.phpnu[#!/usr/bin/env php build/phpdoc latest lib api php stripe-php