CHANGELOG 3.2.2 (19 March 2014) * NEW: Locales set automatically (Feature request #522) * NEW: Mapper dbtype() * NEW: before- and after- triggers for all mappers * NEW: Decode HTML5 entities if PHP>5.3 detected (Feature request #552) * NEW: Send credentials only if AUTH is present in the SMTP extension response (Feature request #545) * NEW: BITMASK variable to allow ENT_COMPAT override * NEW: Redis support for caching * Enable SMTP feature detection * Enable extended ICU custom date format (Feature request #555) * Enable custom time ICU format * Add option to turn off session table creation (Feature request #557) * Enhanced template token rendering and custom filters (Feature request #550) * Avert multiple loads in DB-managed sessions (Feature request #558) * Add EXEC to associative fetch * Bug fix: Building template tokens breaks on inline OR condition (Issue #573) * Bug fix: SMTP->send does not use the $log parameter (Issue #571) * Bug fix: Allow setting sqlsrv primary keys on insert (Issue #570) * Bug fix: Generated query for obtaining table schema in sqlsrv incorrect (Bug #565) * Bug fix: SQL mapper flag set even when value has not changed (Bug #562) * Bug fix: Add XFRAME config option (Feature request #546) * Bug fix: Incorrect parsing of comments (Issue #541) * Bug fix: Multiple Set-Cookie headers (Issue #533) * Bug fix: Mapper is dry after save() * Bug fix: Prevent infinite loop when error handler is triggered (Issue #361) * Bug fix: Mapper tweaks not passing primary keys as arguments * Bug fix: Zero indexes in dot-notated arrays fail to compile * Bug fix: Prevent GROUP clause double-escaping * Bug fix: Regression of zlib compression bug * Bug fix: Method copyto() does not include ad hoc fields * Check existence of OpenID mode (Issue #529) * Generate a 404 when a tokenized class doesn't exist * Fix SQLite quotes (Issue #521) * Bug fix: BASE is incorrect on Windows 3.2.1 (7 January 2014) * NEW: EMOJI variable, UTF->translate(), UTF->emojify(), and UTF->strrev() * Allow empty strings in config() * Add support for turning off php://input buffering via RAW (FALSE by default) * Add Cursor->load() and Cursor->find() TTL support * Support Web->receive() large file downloads via PUT * ONERROR safety check * Fix session CSRF cookie detection * Framework object now passed to route handler contructors * Allow override of DIACRITICS * Various code optimizations * Support log disabling (Issue #483) * Implicit mapper load() on authentication * Declare abstract methods for Cursor derivatives * Support single-quoted HTML/XML attributes (Feature request #503) * Relax property visibility of mappers and derivatives * Deprecated: {{~ ~}} instructions and {{* *}} comments; Use {~ ~} and {* *} instead * Minor fix: Audit->ipv4() return value * Bug fix: Backslashes in BASE not converted on Windows * Bug fix: UTF->substr() with negative offset and specified length * Bug fix: Replace named URL tokens on render() * Bug fix: BASE is not empty when run from document root * Bug fix: stringify() recursion 3.2.0 (18 December 2013) * NEW: Automatic CSRF protection (with IP and User-Agent checks) for sessions mapped to SQL-, Jig-, Mongo- and Cache-based backends * NEW: Named routes * NEW: PATH variable; returns the URL relative to BASE * NEW: Image->captcha() color parameters * NEW: Ability to access MongoCuror thru the cursor() method * NEW: Mapper->fields() method returns array of field names * NEW: Mapper onload(), oninsert(), onupdate(), and onerase() event listeners/triggers * NEW: Preview class (a lightweight template engine) * NEW: rel() method derives path from URL relative to BASE; useful for rerouting * NEW: PREFIX variable for prepending a string to a dictionary term; Enable support for prefixed dictionary arrays and .ini files (Feature request #440) * NEW: Google static map plugin * NEW: devoid() method * Introduce clean(); similar to scrub(), except that arg is passed by value * Use $ttl for cookie expiration (Issue #457) * Fix needs_rehash() cost comparison * Add pass-by-reference argument to exists() so if method returns TRUE, a subsequent get() is unnecessary * Improve MySQL support * Move esc(), raw(), and dupe() to View class where they more appropriately belong * Allow user-defined fields in SQL mapper constructor (Feature request #450) * Re-implement the pre-3.0 template resolve() feature * Remove redundant instances of session_commit() * Add support for input filtering in Mapper->copyfrom() * Prevent intrusive behavior of Mapper->copyfrom() * Support multiple SQL primary keys * Support custom tag attributes/inline tokens defined at runtime (Feature request #438) * Broader support for HTTP basic auth * Prohibit Jig _id clear() * Add support for detailed stringify() output * Add base directory to UI path as fallback * Support Test->expect() chaining * Support __tostring() in stringify() * Trigger error on invalid CAPTCHA length (Issue #458) * Bug fix: exists() pass-by-reference argument returns incorrect value * Bug fix: DB Exec does not return affected row if query contains a sub-SELECT (Issue #437) * Improve seed generator and add code for detecting of acceptable limits in Image->captcha() (Feature request #460) * Add decimal format ICU extension * Bug fix: 404-reported URI contains HTTP query * Bug fix: Data type detection in DB->schema() * Bug fix: TZ initialization * Bug fix: paginate() passes incorrect argument to count() * Bug fix: Incorrect query when reloading after insert() * Bug fix: SQL preg_match error in pdo_type matching (Issue #447) * Bug fix: Missing merge() function (Issue #444) * Bug fix: BASE misdefined in command line mode * Bug fix: Stringifying hive may run infinite (Issue #436) * Bug fix: Incomplete stringify() when DEBUG<3 (Issue #432) * Bug fix: Redirection of basic auth (Issue #430) * Bug fix: Filter only PHP code (including short tags) in templates * Bug fix: Markdown paragraph parser does not convert PHP code blocks properly * Bug fix: identicon() colors on same keys are randomized * Bug fix: quotekey() fails on aliased keys * Bug fix: Missing _id in Jig->find() return value * Bug fix: LANGUAGE/LOCALES handling * Bug fix: Loose comparison in stringify() 3.1.2 (5 November 2013) * Abandon .chm help format; Package API documentation in plain HTML; (Launch lib/api/index.html in your browser) * Deprecate BAIL in favor of HALT (default: TRUE) * Revert to 3.1.0 autoload behavior; Add support for lowercase folder names * Allow Spring-style HTTP method overrides * Add support for SQL Server-based sessions * Capture full X-Forwarded-For header * Add protection against malicious scripts; Extra check if file was really uploaded * Pass-thru page limit in return value of Cursor->paginate() * Optimize code: Implement single-pass escaping * Short circuit Jig->find() if source file is empty * Bug fix: PHP globals passed by reference in hive() result (Issue #424) * Bug fix: ZIP mime type incorrect behavior * Bug fix: Jig->erase() filter malfunction * Bug fix: Mongo->select() group * Bug fix: Unknown bcrypt constant 3.1.1 (13 October 2013) * NEW: Support OpenID attribute exchange * NEW: BAIL variable enables/disables continuance of execution on non-fatal errors * Deprecate BAIL in favor of HALT (default: FALSE) * Add support for Oracle * Mark cached queries in log (Feature Request #405) * Implement Bcrypt->needs_reshash() * Add entropy to SQL cache hash; Add uuid() method to DB backends * Find real document root; Simplify debug paths * Permit OpenID required fields to be declared as comma-separated string or array * Pass modified filename as argument to user-defined function in Web->receive() * Quote keys in optional SQL clauses (Issue #408) * Allow UNLOAD to override fatal error detection (Issue #404) * Mutex operator precedence error (Issue #406) * Bug fix: exists() malfunction (Issue #401) * Bug fix: Jig mapper triggers error when loading from CACHE (Issue #403) * Bug fix: Array index check * Bug fix: OpenID verified() return value * Bug fix: Basket->find() should return a set of results (Issue #407); Also implemented findone() for consistency with mappers * Bug fix: PostgreSQL last insert ID (Issue #410) * Bug fix: $port component URL overwritten by _socket() * Bug fix: Calculation of elapsed time 3.1.0 (20 August 2013) * NEW: Web->filler() returns a chunk of text from the standard Lorem Ipsum passage * Change in behavior: Drop support for JSON serialization * SQL->exec() now returns value of RETURNING clause * Add support for $ttl argument in count() (Issue #393) * Allow UI to be overridden by custom $path * Return result of PDO primitives: begintransaction(), rollback(), and commit() * Full support for PHP 5.5 * Flush buffers only when DEBUG=0 * Support class->method, class::method, and lambda functions as Web->basic() arguments * Commit session on Basket->save() * Optional enlargement in Image->resize() * Support authentication on hosts running PHP-CGI * Change visibility level of Cache properties * Prevent ONERROR recursion * Work around Apache pre-2.4 VirtualDocumentRoot bug * Prioritize cURL in HTTP engine detection * Bug fix: Minify tricky JS * Bug fix: desktop() detection * Bug fix: Double-slash on TEMP-relative path * Bug fix: Cursor mapping of first() and last() records * Bug fix: Premature end of Web->receive() on multiple files * Bug fix: German umlaute to its corresponding grammatically-correct equivalent 3.0.9 (12 June 2013) * NEW: Web->whois() * NEW: Template tags * Improve CACHE consistency * Case-insensitive MIME type detection * Support pre-PHP 5.3.4 in Prefab->instance() * Refactor isdesktop() and ismobile(); Add isbot() * Add support for Markdown strike-through * Work around ODBC's lack of quote() support * Remove useless Prefab destructor * Support multiple cache instances * Bug fix: Underscores in OpenId keys mangled * Refactor format() * Numerous tweaks * Bug fix: MongoId object not preserved * Bug fix: Double-quotes included in lexicon() string (Issue #341) * Bug fix: UTF-8 formatting mangled on Windows (Issue #342) * Bug fix: Cache->load() error when CACHE is FALSE (Issue #344) * Bug fix: send() ternary expression * Bug fix: Country code constants 3.0.8 (17 May 2013) * NEW: Bcrypt lightweight hashing library\ * Return total number of records in superset in Cursor->paginate() * ONERROR short-circuit (Enhancement #334) * Apply quotes/backticks on DB identifiers * Allow enabling/disabling of SQL log * Normalize glob() behavior (Issue #330) * Bug fix: mbstring 2-byte text truncation (Issue #325) * Bug fix: Unsupported operand types (Issue #324) 3.0.7 (2 May 2013) * NEW: route() now allows an array of routing patterns as first argument; support array as first argument of map() * NEW: entropy() for calculating password strength (NIST 800-63) * NEW: AGENT variable containing auto-detected HTTP user agent string * NEW: ismobile() and isdesktop() methods * NEW: Prefab class and descendants now accept constructor arguments * Change in behavior: Cache->exists() now returns timestamp and TTL of cache entry or FALSE if not found (Feature request #315) * Preserve timestamp and TTL when updating cache entry (Feature request #316) * Improved currency formatting with C99 compliance * Suppress unnecessary program halt at startup caused by misconfigured server * Add support for dashes in custom attribute names in templates * Bug fix: Routing precedene (Issue #313) * Bug fix: Remove Jig _id element from document property * Bug fix: Web->rss() error when not enough items in the feed (Issue #299) * Bug fix: Web engine fallback (Issue #300) * Bug fix: and formatting * Bug fix: Text rendering of text with trailing punctuation (Issue #303) * Bug fix: Incorrect regex in SMTP 3.0.6 (31 Mar 2013) * NEW: Image->crop() * Modify documentation blocks for PHPDoc interoperability * Allow user to control whether Base->rerouet() uses a permanent or temporary redirect * Allow JAR elements to be set individually * Refactor DB\SQL\Mapper->insert() to cope with autoincrement fields * Trigger error when captcha() font is missing * Remove unnecessary markdown regex recursion * Check for scalars instead of DB\SQL strings * Implement more comprehensive diacritics table * Add option for disabling 401 errors when basic auth() fails * Add markdown syntax highlighting for Apache configuration * Markdown->render() deprecated to remove dependency on UI variable; Feature replaced by Markdown->convert() to enable translation from markdown string to HTML * Optimize factory() code of all data mappers * Apply backticks on MySQL table names * Bug fix: Routing failure when directory path contains a tilde (Issue #291) * Bug fix: Incorrect markdown parsing of strong/em sequences and inline HTML * Bug fix: Cached page not echoed (Issue #278) * Bug fix: Object properties not escaped when rendering * Bug fix: OpenID error response ignored * Bug fix: memcache_get_extended_stats() timeout * Bug fix: Base->set() doesn't pass TTL to Cache->set() * Bug fix: Base->scrub() ignores pass-thru * argument (Issue #274) 3.0.5 (16 Feb 2013) * NEW: Markdown class with PHP, HTML, and .ini syntax highlighting support * NEW: Options for caching of select() and find() results * NEW: Web->acceptable() * Add send() argument for forcing downloads * Provide read() option for applying Unix LF as standard line ending * Bypass lexicon() call if LANGUAGE is undefined * Load fallback language dictionary if LANGUAGE is undefined * map() now checks existence of class/methods for non-tokenized URLs * Improve error reporting of non-existent Template methods * Address output buffer issues on some servers * Bug fix: Setting DEBUG to 0 won't suppress the stack trace when the content type is application/json (Issue #257) * Bug fix: Image dump/render additional arguments shifted * Bug fix: ob_clean() causes buffer issues with zlib compression * Bug fix: minify() fails when commenting CSS @ rules (Issue #251) * Bug fix: Handling of commas inside quoted strings * Bug fix: Glitch in stringify() handling of closures * Bug fix: dry() in mappers returns TRUE despite being hydrated by factory() (Issue #265) * Bug fix: expect() not handling flags correctly * Bug fix: weather() fails when server is unreachable 3.0.4 (29 Jan 2013) * NEW: Support for ICU/CLDR pluralization * NEW: User-defined FALLBACK language * NEW: minify() now recognizes CSS @import directives * NEW: UTF->bom() returns byte order mark for UTF-8 encoding * Expose SQL\Mapper->schema() * Change in behavior: Send error response as JSON string if AJAX request is detected * Deprecated: afind*() methods * Discard output buffer in favor of debug output * Make _id available to Jig queries * Magic class now implements ArrayAccess * Abort execution on startup errors * Suppress stack trace on DEBUG level 0 * Allow single = as equality operator in Jig query expressions * Abort OpenID discovery if Web->request() fails * Mimic PHP *RECURSION* in stringify() * Modify Jig parser to allow wildcard-search using preg_match() * Abort execution after error() execution * Concatenate cached/uncached minify() iterations; Prevent spillover caching of previous minify() result * Work around obscure PHP session id regeneration bug * Revise algorithm for Jig filter involving undefined fields (Issue #230) * Use checkdnsrr() instead of gethostbyname() in DNSBL check * Auto-adjust pagination to cursor boundaries * Add Romanian diacritics * Bug fix: Root namespace reference and sorting with undefined Jig fields * Bug fix: Greedy receive() regex * Bug fix: Default LANGUAGE always 'en' * Bug fix: minify() hammers cache backend * Bug fix: Previous values of primary keys not saved during factory() instantiation * Bug fix: Jig find() fails when search key is not present in all records * Bug fix: Jig SORT_DESC (Issue #233) * Bug fix: Error reporting (Issue #225) * Bug fix: language() return value 3.0.3 (29 Dec 2013) * NEW: [ajax] and [sync] routing pattern modifiers * NEW: Basket class (session-based pseudo-mapper, shopping cart, etc.) * NEW: Test->message() method * NEW: DB profiling via DB->log() * NEW: Matrix->calendar() * NEW: Audit->card() and Audit->mod10() for credit card verification * NEW: Geo->weather() * NEW: Base->relay() accepts comma-separated callbacks; but unlike Base->chain(), result of previous callback becomes argument of the next * Numerous performance tweaks * Interoperability with new MongoClient class * Web->request() now recognizes gzip and deflate encoding * Differences in behavior of Web->request() engines rectified * mutex() now uses an ID as argument (instead of filename to make it clear that specified file is not the target being locked, but a primitive cross-platform semaphore) * DB\SQL\Mapper field _id now returned even in the absence of any auto-increment field * Magic class spinned off as a separate file * ISO 3166-1 alpha-2 table updated * Apache redirect emulation for PHP 5.4 CLI server mode * Framework instance now passed as argument to any user-defined shutdown function * Cache engine now used as storage for Web->minify() output * Flag added for enabling/disabling Image class filter history * Bug fix: Trailing routing token consumes HTTP query * Bug fix: LANGUAGE spills over to LOCALES setting * Bug fix: Inconsistent dry() return value * Bug fix: URL-decoding 3.0.2 (23 Dec 2013) * NEW: Syntax-highlighted stack traces via Base->highlight(); boolean HIGHLIGHT global variable can be used to enable/disable this feature * NEW: Template engine tag * NEW: Image->captcha() * NEW: DNSBL-based spammer detection (ported from 2.x) * NEW: paginate(), first(), and last() methods for data mappers * NEW: X-HTTP-Method-Override header now recognized * NEW: Base->chain() method for executing callbacks in succession * NEW: HOST global variable; derived from either $_SERVER['SERVER_NAME'] or gethostname() * NEW: REALM global variable representing full canonical URI * NEW: Auth plug-in * NEW: Pingback plug-in (implements both Pingback 1.0 protocol client and server) * NEW: DEBUG verbosity can now reach up to level 3; Base->stringify() drills down to object properties at this setting * NEW: HTTP PATCH method added to recognized HTTP ReST methods * Web->slug() now trims trailing dashes * Web->request() now allows relative local URLs as argument * Use of PARAMS in route handlers now unnecessary; framework now passes two arguments to route handlers: the framework object instance and an array containing the captured values of tokens in route patterns * Standardized timeout settings among Web->request() backends * Session IDs regenerated for additional security * Automatic HTTP 404 responses by Base->call() now restricted to route handlers * Empty comments in ini-style files now parsed properly * Use file_get_contents() in methods that don't involve high concurrency 3.0.1 (14 Dec 2013) * Major rewrite of much of the framework's core features