query($sql);
if(!$res)
throw new Exception("I can't read German: " . $db->error);
if($res->num_rows == 0)
return NULL;
$item = $res->fetch_assoc();
$res->close();
return $item;
}
// takes: arrays $fields, $tables, $where, $order, int $limit
// returns: associative array of associative arrays of matching rows
public static function get_all( $fields = array("*"),
$tables = array("objects"),
$where = array(),
$order = array(),
$limit = '',
$descending = FALSE,
$distinct = FALSE)
// $distinct = TRUE)
{
global $db;
$sql = "SELECT ";
if($distinct)
$sql .= "DISTINCT ";
$sql .= implode(", ", $fields) . " ";
$sql .= "FROM " . implode(", ", $tables) . " ";
if (!empty($where))
$sql .= "WHERE " . implode(" AND ", $where) . " ";
if (!empty($order))
$sql .= "ORDER BY " . implode(", ", $order) . " ";
if (!empty($limit))
$sql .= "LIMIT " . $limit;
if ($descending)
$sql .= " DESC";
$res = $db->query($sql);
if(!$res)
throw new Exception($db->error);
$items = array();
while ($obj = $res->fetch_assoc())
$items[] = $obj;
$res->close();
return $items;
}
// inserts a new row into the db
// $arr is an associative array of col => value
//
// TODO:
// + VERIFY INPUTS
public static function insert($arr)
{
global $db;
$dt = date(self::MYSQL_DATE_FMT);
$arr["created"] = "'".$dt."'";
$arr["modified"] = "'".$dt."'";
$keys = array();
foreach(array_keys($arr) as $k)
$keys[] = "`".$k."`";
$keys = implode(", ", $keys);
$values = implode(", ", array_values($arr));
$sql = "INSERT INTO " . static::table_name . " (";
$sql .= $keys . ") VALUES(" . $values . ")";
$db->query($sql);
return $db->insert_id;
}
// updates a row of the db associated with a particular $id
// $id is the id of the object / wire / media to be updated
// $arr is an associative array of col => value
//
// TODO:
// + VERIFY INPUTS
public static function update($id, $arr)
{
global $db;
$dt = date(self::MYSQL_DATE_FMT);
$arr["modified"] = "'".$dt."'";
foreach($arr as $key => $value)
$pairs[] = "`".$key."`"."=".$value;
$z = implode(", ", $pairs);
$sql = "UPDATE ".static::table_name."
SET ".$z."
WHERE id = '".$id."'";
return $db->query($sql);
}
// deactivate row with id = $id
// ie, set active to 0
public function deactivate($id)
{
global $db;
if(!is_numeric($id))
throw new Exception('Id not numeric.');
$sql = "UPDATE ".static::table_name."
SET active = '0',
modified = '".date(self::MYSQL_DATE_FMT)."'
WHERE id = '$id'";
if($db->query($sql) === TRUE)
return "Record deleted sucessfully.";
else
return "error: " . $db->error;
}
// returns true if the row associated with $id is active,
// false if not
public function active($id)
{
$item = $this->get($id);
return $item["active"] == 1;
}
// returns the number of rows in the table associated with
// this object
public function num_rows()
{
global $db;
$sql = "SELECT COUNT(id) from ".static::table_name;
$res = $db->query($sql);
$item = $res->fetch_assoc();
$res->close();
return $item["COUNT(id)"];
}
}
?>
get($o);
return $item["name1"];
}
// return the children of object with id $o
public function children($o)
{
$fields = array("objects.*");
$tables = array("objects", "wires");
$where = array("wires.fromid = '".$o."'",
"wires.active = 1",
"wires.toid = objects.id",
"objects.active = '1'");
$order = array("objects.rank", "objects.begin", "objects.end", "objects.name1");
/* exception for ICA, applies globally */
// $order = array("objects.rank", "objects.modified DESC", "objects.end", "objects.begin", "objects.name1");
return $this->get_all($fields, $tables, $where, $order);
}
// returns: the ids of all children of object with id $o
public function children_ids($o)
{
$fields = array("objects.id AS id",
"objects.rank",
"objects.name1");
$tables = array("objects", "wires");
$where = array("wires.fromid = '".$o."'",
"wires.active = 1",
"wires.toid = objects.id",
"objects.active = '1'");
$order = array("objects.rank", "objects.begin", "objects.end", "objects.name1");
$res = $this->get_all($fields, $tables, $where, $order);
$ids = array();
foreach($res as $r)
$ids[] = $r['id'];
return $ids;
}
public function children_ids_nav($o)
{
$fields = array("objects.*");
$tables = array("objects", "wires");
$where = array("wires.fromid = '".$o."'",
"wires.active = 1",
"wires.toid = objects.id",
"objects.active = '1'",
"objects.name1 not like '.%'");
$order = array("objects.rank", "objects.begin", "objects.end", "objects.name1");
$res = $this->get_all($fields, $tables, $where, $order);
$ids = array();
foreach($res as $r)
$ids[] = $r['id'];
return $ids;
}
public function siblings($o)
{
global $db;
$siblings = array();
$sql = "SELECT wires.fromid FROM wires, objects
WHERE wires.toid = '" . $o . "'
AND ((objects.id = wires.fromid
AND objects.active = '1' )
OR (wires.fromid = '0' AND objects.id = wires.toid))";
$res = $db->query($sql);
if(!$res)
throw new Exception($db->error);
$fromid_arr = array();
while ($obj = $res->fetch_assoc())
$fromid_arr[] = $obj['fromid'];
$res->close();
foreach($fromid_arr as $parent_id)
{
$this_siblings = $this->children_ids($parent_id);
foreach($this_siblings as $key => $s_id)
{
if($s_id == $o)
unset($this_siblings[$key]);
}
$this_siblings = array_values($this_siblings);
$siblings = array_merge($siblings, $this_siblings);
}
return $siblings;
}
// check that URL is of valid object here
// throw 404 exception if not
public function urls_to_ids($u)
{
$fromid = 0;
$objects = array();
for($i = 0; $i < count($u); $i++)
{
$fields = array("objects.id",
"objects.name1");
$tables = array("objects", "wires");
$where = array("wires.fromid = '".$fromid."'",
"wires.toid = objects.id",
"objects.url = '".$u[$i]."'",
"wires.active = '1'",
"objects.active = '1'");
$order = array("objects.rank", "objects.begin", "objects.end", "objects.name1");
$tmp = $this->get_all($fields, $tables, $where, $order);
if(!empty($tmp))
{
$fromid = $tmp[0]['id'];
if(!$fromid)
throw new Exception($i);
$objects[] = $fromid;
}
}
return $objects;
}
public function ids_to_urls($objects)
{
$u = array();
for($i = 0; $i < count($objects); $i++)
{
$o = $this->get($objects[$i]);
$u[] = $o['url'];
}
return $u;
}
// returns: the ids of all ancestors of object with id $o
//
// ancestors are obtained by traversing tree,
// going through in-order list of traversals,
// recording potential parents,
// breaking when $o is found,
// reporting the actual parents at the time of finding
// repeats this process through the entire tree array, in case
// object is linked elsewhere
/*
major performance issues on ica.art. the issue is:
> $all = $this->traverse(0);
which does not scale efficiently to the size of ica.art database
*/
// added $force to ONLY call if absolutely required
// added $all (if available) to avoid traverse(0) again
public function ancestors($o, $all = NULL, $force = FALSE)
{
$ancestors = array();
if ($force) {
if (!$all)
$all = $this->traverse(0);
$a = array();
for($i = 0; $i < count($all); $i++)
{
if(end($all[$i]) == $o)
{
$d = count($all[$i]);
$ancestors = array_merge($ancestors, array_slice($a, 0, $d-1));
}
$d = count($all[$i]);
$a[$d-1] = end($all[$i]);
}
}
return array_unique($ancestors);
}
public function ancestors_single($root, $o)
{
$all = $this->traverse($root);
$ancestors = array();
$a = array();
for($i = 0; $i < count($all); $i++)
{
if(end($all[$i]) == $o)
{
$d = count($all[$i]);
$ancestors = array_slice($a, 0, $d-1);
}
$d = count($all[$i]);
$a[$d-1] = end($all[$i]);
}
return $ancestors;
}
// returns: the ids of all descedants of object with id $o
// children, grandchildren, etc
public function descendants($o)
{
$desc = $this->traverse($o);
$descendants = array();
foreach($desc as $d)
$descendants[] = end($d);
return $descendants;
}
// return media attached to this object
public function media($o)
{
$fields = array("*");
$tables = array("media");
$where = array("object = '".$o."'",
"active = '1'");
$order = array("media.rank", "media.modified", "media.created", "media.id");
return $this->get_all($fields, $tables, $where, $order);
}
public function media_ids($o)
{
$fields = array("id");
$tables = array("media");
$where = array("object = '".$o."'",
"active = '1'");
$order = array("media.rank", "media.modified", "media.created", "media.id");
$res = $this->get_all($fields, $tables, $where, $order);
$ids = array();
foreach($res as $r)
$ids[] = $r['id'];
return $ids;
}
// returns a list of objects $o can link to
// $o cannot link to its children
// (because it is already linked to them)
// or any of its direct ancestors
// (because doing so would create a loop)
// optimized using mysql query in place of multiple array_merge()
// get every record that is neither parent nor child nor itself
// return only one record per object even if linked multiple times
// ie, multiple wires in database
// public function link_list($o)
// {
// global $db;
// $id = $o;
// $tab = ' ';
// // ids_to_exclude: ancestors, self, children
// $ids_to_exclude = array();
// $sql_getAncestors = "WITH RECURSIVE cte (fromid) AS (
// SELECT fromid FROM wires WHERE toid = '$id' AND active = '1'
// UNION ALL
// SELECT w.fromid FROM cte c JOIN wires w ON c.fromid = w.toid WHERE c.fromid != '0')
// SELECT * FROM cte";
// $res = $db->query($sql_getAncestors);
// while ($obj = $res->fetch_assoc())
// $ids_to_exclude[] = $obj['fromid'];
// $ids_to_exclude[] = $id;
// $ids_to_exclude = array_merge($ids_to_exclude, $this->children_ids($id));
// return $this->traverse_recursive($id, $ids_to_exclude);
// }
public function get_ancestors_and_children($o)
{
global $db;
$id = $o;
$tab = ' ';
$output = array(
'ancestors' => array(),
'self' => $id,
'children' => array()
);
$sql_getAncestors = "WITH RECURSIVE cte (fromid) AS (
SELECT fromid FROM wires WHERE toid = '$id' AND active = '1'
UNION ALL
SELECT w.fromid FROM cte c JOIN wires w ON c.fromid = w.toid WHERE c.fromid != '0')
SELECT * FROM cte";
$res = $db->query($sql_getAncestors);
while ($obj = $res->fetch_assoc())
$output['ancestors'][] = $obj['fromid'];
$output['children'] = $this->children_ids($id);
return $output;
}
// returns an array of [path] of objects rooted at $o
// depth is equal to the length of each path array
public function traverse($o)
{
static $path = array();
$children_ids = $this->children_ids($o);
$paths = array();
if(count($path) > 0)
$paths[] = $path;
if(!empty($children_ids)) // make children return an empty array?
{
foreach($children_ids as $c)
{
$path[] = $c;
$paths = array_merge($paths, $this->traverse($c));
array_pop($path);
}
}
return $paths;
}
// public function traverse_recursive($o, $excludes = array()){
// global $db;
// $id = $o;
// $tab = ' ';
// $excludes_command = empty($excludes) ? 'false' : 'IF(wires.toid IN (' . implode(',', $excludes) . '), true,false)';
// $sql = "WITH RECURSIVE cte ( `toid`, `name1`, `indent`, `path_string`, `path`, `exclude`) AS (
// SELECT wires.toid, objects.name1, CAST( '' AS CHAR(512) ), objects.name1, CAST( objects.id AS CHAR(512) ), $excludes_command FROM wires, objects WHERE objects.active = '1' AND wires.active = '1' AND objects.id = wires.toid AND wires.fromid = '0'
// UNION ALL
// SELECT wires.toid, objects.name1, CONCAT( cte.indent, '$tab' ), CONCAT( cte.path_string, ' > ', objects.name1 ), CONCAT( cte.path, ',', objects.id ), $excludes_command FROM cte INNER JOIN wires ON cte.toid = wires.fromid INNER JOIN objects ON wires.toid = objects.id AND wires.active = '1' AND objects.active = '1'
// )
// SELECT * FROM cte ORDER BY `path_string`";
// $items = array();
// $res = $db->query($sql);
// while($obj = $res->fetch_assoc()){
// $obj['path'] = explode(',', $obj['path']);
// $items[] = $obj;
// }
// return $items;
// }
public function traverse_recursive($root, $reference=false, $excludes = array()){
global $db;
$reference = $reference ? $reference : $root;
$id = $root;
$tab = ' ';
$excludes_command = empty($excludes) ? 'false' : 'IF(wires.toid IN (' . implode(',', $excludes) . '), true,false)';
$ancestors_and_children = $this->get_ancestors_and_children($reference);
// var_dump($reference);
$ancestors_str = '(' . implode(',', $ancestors_and_children['ancestors']) . ')';
$children_str = '(' . implode(',', $ancestors_and_children['children']) . ')';
// $roles_command = "IF(wires.toid = $reference, 'self', IF(wires.toid IN $ancestors_str, 'ancestor', IF(wires.toid)))";
$role_command = "CASE WHEN wires.toid = $reference THEN 'self'";
if(!empty($ancestors_and_children['ancestors'])) $role_command .= " WHEN wires.toid IN (" . implode(',', $ancestors_and_children['ancestors']) . ") THEN 'ancestor'";
if(!empty($ancestors_and_children['children'])) $role_command .= " WHEN wires.toid IN (" . implode(',', $ancestors_and_children['children']) . ") THEN 'child'";
$role_command .= " ELSE '' END";
$sql = "WITH RECURSIVE cte ( `toid`, `name1`, `indent`, `path_string`, `path`, `role`, `exclude`) AS (
SELECT wires.toid, objects.name1, CAST( '' AS CHAR(512) ), objects.name1, CAST( objects.id AS CHAR(512) ), $role_command, $excludes_command FROM wires, objects WHERE objects.active = '1' AND wires.active = '1' AND objects.id = wires.toid AND wires.fromid = '$id'
UNION ALL
SELECT wires.toid, objects.name1, CONCAT( cte.indent, '$tab' ), CONCAT( cte.path_string, ' > ', objects.name1 ), CONCAT( cte.path, ',', objects.id ), $role_command, $excludes_command FROM cte INNER JOIN wires ON cte.toid = wires.fromid INNER JOIN objects ON wires.toid = objects.id AND wires.active = '1' AND objects.active = '1'
)
SELECT * FROM cte ORDER BY `path_string`";
$items = array();
$res = $db->query($sql);
while($obj = $res->fetch_assoc()){
$obj['path'] = explode(',', $obj['path']);
$items[] = $obj;
}
return $items;
}
// takes: a tree constructed by $oo->traverse()
// returns; an associative array of depth, name, url
public function nav_full($paths)
{
$urls = array();
$prevd = 0;
$nav = array();
foreach($paths as $path)
{
$d = count($path);
$o = $this->get($path[(count($path)-1)]);
$pops = $prevd - $d + 1;
$urls = array_slice($urls, 0, count($urls) - $pops);
$urls[] = $o['url'];
$url = implode("/", $urls);
$nav[] = array('depth'=>$d, 'o'=>$o, 'url'=>$url);
$prevd = $d;
}
return $nav;
}
// takes:
// returns:
// if end($ids) is a leaf (has no siblings), then return the siblings with the
// tree
public function nav($ids, $root_id=0)
{
$nav = array();
$pass = true;
$top = $this->children_ids_nav($root_id);
$ids = array_search($root_id, $ids) === FALSE ? $ids : array_slice($ids, 1);
$root_index = array_search($root_id, $ids) === FALSE ? 0 : array_search($root_id, $ids);
foreach($top as $t)
{
$o = $this->get($t);
$d = $root_index+1;
$urls = array($o['url']);
$url = implode("/", $urls);
$nav[] = array('depth'=>$d, 'o'=>$o, 'url'=>$url);
if(!empty($ids) && isset($ids[$root_index]) && $pass && $t == $ids[$root_index])
{
$pass = false; // short-circuit if statement
$kids = $this->children_ids_nav(end($ids));
if(empty($kids) && count($ids) > 1)
{
$kids = $this->children_ids_nav($ids[count($ids)-2]);
array_pop($ids); // leaf is included in siblings
}
array_shift($ids);
// show direct ancestors (and self, if children)
foreach(array_slice($ids, $root_index) as $id)
{
$d++;
$o = $this->get($id);
$urls[] = $o['url'];
$url = implode("/", $urls);
$nav[] = array('depth'=>$d, 'o'=>$o, 'url'=>$url);
}
// show children, if no children, show self + siblings
$d++;
foreach($kids as $k)
{
$o = $this->get($k);
$urls[] = $o['url'];
$url = implode("/", $urls);
$nav[] = array('depth'=>$d, 'o'=>$o, 'url'=>$url);
array_pop($urls);
}
}
}
return $nav;
}
function nav_helper($type, $id, $d, &$urls)
{
$o = $this->get($id);
$urls[] = $o['url'];
$url = implode("/", $urls);
return array('type'=>$type, 'id'=>$id,'o'=>$o,'depth'=>$d,'url'=>$url);
}
public function nav_test($ids, $root=0)
{
$top = $this->children_ids($root);
}
// takes: an array of ids
// returns: an array of arrays corresponding to a
// very specific traversal of the tree
// all top-level nodes are returned
// all 'parents' w/r/t to the array of ids are returned
// if the last node in ids has children, children are also returned
// if not, siblings are returned
public function nav_clean($ids, $root=0)
{
$records = array();
$top = $this->children_ids($root);
$pass = true;
$root_i = array_search($root, $ids);
if($root_i === FALSE)
$root_i = 0;
else
$root_i++;
foreach($top as $t_id)
{
$d = 1;
// urls to be appended to the beginning of each menu item
$urls = array("de");
// if this top-level object is an ancestor of the current obj
if($pass && $t_id == $ids[$root_i])
{
$pass = false; // short-circuit if-statement
$s_id = array_pop($ids);
// parents
foreach(array_slice($ids, $root_i) as $p_id)
$records[] = $this->nav_helper("parent", $p_id, $d++, $urls);
$kids = $this->children_ids($s_id);
// self + siblings
if(empty($kids))
{
if(count($ids))
{
$siblings = $this->children_ids(end($ids));
foreach($siblings as $sib)
{
if($sib == $s_id)
$records[] = $this->nav_helper("self", $sib, $d, $urls);
else
$records[] = $this->nav_helper("sibling", $sib, $d, $urls);
array_pop($urls);
}
}
else
$records[] = $this->nav_helper("self", $s_id, $d, $urls);
}
// self + kids
else
{
$records[] = $this->nav_helper("self", $s_id, $d++, $urls);
foreach($kids as $k_id)
{
$records[] = $this->nav_helper("child", $k_id, $d, $urls);
array_pop($urls);
}
}
}
else
$records[] = $this->nav_helper("top", $t_id, $d, $urls);
}
return $records;
}
}
?>
get_all($fields, $tables, $where, $order, $limit);
return $wire[0];
}
public function get_wires_to($toid)
{
$fields = array("*");
$tables = array(static::table_name);
$where = array("toid = '".$toid."'",
"active = '1'");
$order = array();
$wires = $this->get_all($fields, $tables, $where, $order);
return $wires;
}
public function get_wires_from($fromid)
{
$fields = array("*");
$tables = array(static::table_name);
$where = array("fromid = '".$fromid."'",
"active = '1'");
$order = array();
$wires = $this->get_all($fields, $tables, $where, $order);
return $wires;
}
public function delete_wire($fromid, $toid)
{
$item = $this->get_wire($fromid, $toid);
$w = $item["id"];
return $this->deactivate($w);
}
public function create_wire($fromid, $toid)
{
$dt = date("Y-m-d H:i:s");
// $arr["created"] = "'".$dt."'";
// $arr["modified"] = "'".$dt."'";
$arr["fromid"] = $fromid;
$arr["toid"] = $toid;
return $this->insert($arr);
}
}
?> '+'
// rawurlencode() is for urls, ' ' -> '%20'
// $tmp = urlencode($tmp);
$tmp = rawurlencode($tmp);
return $tmp;
}
// return a string of random characters [a-z, 0-9]
// of length $len
function rand_str($len=4)
{
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$max = strlen($chars)-1;
$s = "";
for($i = 0; $i < $len; $i++)
{
$c = substr($chars, rand(0, $max), 1);
$s.= $c;
}
return $s;
}
// for our purposes, $alt is assumed to be the id of the object
// this url is meant to reference
function valid_url($u, $alt, $excludes)
{
// array_search returns the position (index) of $u in
// $excludes, or false if not present in the array.
// therefore, strict compare to false
if( $alt < 10 )
$alt = '000' . $alt;
else if($alt < 100)
$alt = '00' . $alt;
else if($alt < 1000)
$alt = '0' . $alt;
$url = $u . '-' . $alt;
while(array_search($url, $excludes) !== false)
$url = $u . '-' . rand(1000, 9999);
return $url;
}
function validate_url($u, $excludes)
{
if(empty($u) || array_search($u, $excludes) !== false)
return false;
else
return true;
}
// why do i need two of these?
// which would be better to keep? probably the second one.
// maybe the variables should be passed instead of called on globally
function m_pad($m)
{
global $m_pad;
return str_pad($m, $m_pad, "0", STR_PAD_LEFT);
}
function m_url($m)
{
global $media_path;
return $media_path.m_pad($m['id']).".".$m['type'];
}
function m_root($m)
{
global $media_root;
return $media_root.m_pad($m['id']).".".$m['type'];
}
// this has not been tested
function resize($src, $dest, $scale)
{
include('lib/SimpleImage.php');
$si = new SimpleImage();
$si->load($src);
$si->scale($scale);
$si->save($dest);
}
function md2html($md)
{
if(!$md)
return "";
$p = "/usr/home/lilyhealey/public_html/dev.lilyhealey.co.uk/lib/";
$f = "out.txt";
file_put_contents($p.$f, $md);
exec($p."Markdown.pl ".$p.$f, $html);
unlink($p.$f);
return implode("\n", $html);
}
function html2md($html)
{
if(!$html)
return "";
$p = "/usr/home/lilyhealey/public_html/dev.lilyhealey.co.uk/lib/";
$f = "out.txt";
file_put_contents($p.$f, $html);
exec($p."html2text.py ".$p.$f, $md);
unlink($p.$f);
return implode("\n", $md);
}
function process_media($toid)
{
global $mm;
global $rr;
global $resize;
global $resize_root;
global $resize_scale;
global $media_root;
$m_rows = $mm->num_rows();
$m_old = $m_rows;
foreach($_FILES["uploads"]["error"] as $key => $error)
{
if($error == UPLOAD_ERR_OK)
{
$tmp_name = $_FILES["uploads"]["tmp_name"][$key];
$m_name = $_FILES["uploads"]["name"][$key];
$temp = explode(".", $m_name);
$m_type = strtolower(end($temp));
// add to db's image list
$m_arr["type"] = "'".$m_type."'";
$m_arr["object"] = "'".$toid."'";
if($rr->captions != null){
$count_media = $rr->medias == null ? 0 : count($rr->medias);
if( isset($rr->captions[$key+$count_media]) )
$m_arr["caption"] = "'".$rr->captions[$key+$count_media]."'";
else
$m_arr["caption"] = "''";
}
else
$m_arr["caption"] = "''";
$insert_id = $mm->insert($m_arr);
$m_rows++;
$m_file = m_pad($insert_id).".".$m_type;
$m_dest = $resize ? $resize_root : $media_root;
$m_dest.= $m_file;
if(move_uploaded_file($tmp_name, $m_dest)) {
if($resize)
resize($m_dest, $media_root.$m_file, $resize_scale);
}
else {
$m_rows--;
$mm->deactivate($insert_id);
}
}
}
return $m_old < $m_rows;
}
// remove_accents adapted from wordpress core
// converts all accent characters to ASCII characters.
// if there are no accent characters, then the string given is just returned.
// https://core.trac.wordpress.org/browser/tags/3.9.1/src/wp-includes/formatting.php#L682
// https://stackoverflow.com/questions/1017599/how-do-i-remove-accents-from-characters-in-a-php-string
// called in slug() to force all characters in url slug to ascii before write to db
/*
character conversion reference
À => A
Á => A
 => A
à => A
Ä => A
Å => A
Ç => C
È => E
É => E
Ê => E
Ë => E
Ì => I
Í => I
Î => I
Ï => I
Ñ => N
Ò => O
Ó => O
Ô => O
Õ => O
Ö => O
Ù => U
Ú => U
Û => U
Ü => U
Ý => Y
ß => s
à => a
á => a
â => a
ã => a
ä => a
å => a
ç => c
è => e
é => e
ê => e
ë => e
ì => i
í => i
î => i
ï => i
ñ => n
ò => o
ó => o
ô => o
õ => o
ö => o
ù => u
ú => u
û => u
ü => u
ý => y
ÿ => y
Ā => A
ā => a
Ă => A
ă => a
Ą => A
ą => a
Ć => C
ć => c
Ĉ => C
ĉ => c
Ċ => C
ċ => c
Č => C
č => c
Ď => D
ď => d
Đ => D
đ => d
Ē => E
ē => e
Ĕ => E
ĕ => e
Ė => E
ė => e
Ę => E
ę => e
Ě => E
ě => e
Ĝ => G
ĝ => g
Ğ => G
ğ => g
Ġ => G
ġ => g
Ģ => G
ģ => g
Ĥ => H
ĥ => h
Ħ => H
ħ => h
Ĩ => I
ĩ => i
Ī => I
ī => i
Ĭ => I
ĭ => i
Į => I
į => i
İ => I
ı => i
IJ => IJ
ij => ij
Ĵ => J
ĵ => j
Ķ => K
ķ => k
ĸ => k
Ĺ => L
ĺ => l
Ļ => L
ļ => l
Ľ => L
ľ => l
Ŀ => L
ŀ => l
Ł => L
ł => l
Ń => N
ń => n
Ņ => N
ņ => n
Ň => N
ň => n
ʼn => N
Ŋ => n
ŋ => N
Ō => O
ō => o
Ŏ => O
ŏ => o
Ő => O
ő => o
Œ => OE
œ => oe
Ŕ => R
ŕ => r
Ŗ => R
ŗ => r
Ř => R
ř => r
Ś => S
ś => s
Ŝ => S
ŝ => s
Ş => S
ş => s
Š => S
š => s
Ţ => T
ţ => t
Ť => T
ť => t
Ŧ => T
ŧ => t
Ũ => U
ũ => u
Ū => U
ū => u
Ŭ => U
ŭ => u
Ů => U
ů => u
Ű => U
ű => u
Ų => U
ų => u
Ŵ => W
ŵ => w
Ŷ => Y
ŷ => y
Ÿ => Y
Ź => Z
ź => z
Ż => Z
ż => z
Ž => Z
ž => z
ſ => s
*/
function remove_accents($string) {
if ( !preg_match('/[\x80-\xff]/', $string) )
return $string;
$chars = array(
// Decompositions for Latin-1 Supplement
chr(195).chr(128) => 'A', chr(195).chr(129) => 'A',
chr(195).chr(130) => 'A', chr(195).chr(131) => 'A',
chr(195).chr(132) => 'A', chr(195).chr(133) => 'A',
chr(195).chr(135) => 'C', chr(195).chr(136) => 'E',
chr(195).chr(137) => 'E', chr(195).chr(138) => 'E',
chr(195).chr(139) => 'E', chr(195).chr(140) => 'I',
chr(195).chr(141) => 'I', chr(195).chr(142) => 'I',
chr(195).chr(143) => 'I', chr(195).chr(145) => 'N',
chr(195).chr(146) => 'O', chr(195).chr(147) => 'O',
chr(195).chr(148) => 'O', chr(195).chr(149) => 'O',
chr(195).chr(150) => 'O', chr(195).chr(153) => 'U',
chr(195).chr(154) => 'U', chr(195).chr(155) => 'U',
chr(195).chr(156) => 'U', chr(195).chr(157) => 'Y',
chr(195).chr(159) => 's', chr(195).chr(160) => 'a',
chr(195).chr(161) => 'a', chr(195).chr(162) => 'a',
chr(195).chr(163) => 'a', chr(195).chr(164) => 'a',
chr(195).chr(165) => 'a', chr(195).chr(167) => 'c',
chr(195).chr(168) => 'e', chr(195).chr(169) => 'e',
chr(195).chr(170) => 'e', chr(195).chr(171) => 'e',
chr(195).chr(172) => 'i', chr(195).chr(173) => 'i',
chr(195).chr(174) => 'i', chr(195).chr(175) => 'i',
chr(195).chr(177) => 'n', chr(195).chr(178) => 'o',
chr(195).chr(179) => 'o', chr(195).chr(180) => 'o',
chr(195).chr(181) => 'o', chr(195).chr(182) => 'o',
chr(195).chr(182) => 'o', chr(195).chr(185) => 'u',
chr(195).chr(186) => 'u', chr(195).chr(187) => 'u',
chr(195).chr(188) => 'u', chr(195).chr(189) => 'y',
chr(195).chr(191) => 'y',
// Decompositions for Latin Extended-A
chr(196).chr(128) => 'A', chr(196).chr(129) => 'a',
chr(196).chr(130) => 'A', chr(196).chr(131) => 'a',
chr(196).chr(132) => 'A', chr(196).chr(133) => 'a',
chr(196).chr(134) => 'C', chr(196).chr(135) => 'c',
chr(196).chr(136) => 'C', chr(196).chr(137) => 'c',
chr(196).chr(138) => 'C', chr(196).chr(139) => 'c',
chr(196).chr(140) => 'C', chr(196).chr(141) => 'c',
chr(196).chr(142) => 'D', chr(196).chr(143) => 'd',
chr(196).chr(144) => 'D', chr(196).chr(145) => 'd',
chr(196).chr(146) => 'E', chr(196).chr(147) => 'e',
chr(196).chr(148) => 'E', chr(196).chr(149) => 'e',
chr(196).chr(150) => 'E', chr(196).chr(151) => 'e',
chr(196).chr(152) => 'E', chr(196).chr(153) => 'e',
chr(196).chr(154) => 'E', chr(196).chr(155) => 'e',
chr(196).chr(156) => 'G', chr(196).chr(157) => 'g',
chr(196).chr(158) => 'G', chr(196).chr(159) => 'g',
chr(196).chr(160) => 'G', chr(196).chr(161) => 'g',
chr(196).chr(162) => 'G', chr(196).chr(163) => 'g',
chr(196).chr(164) => 'H', chr(196).chr(165) => 'h',
chr(196).chr(166) => 'H', chr(196).chr(167) => 'h',
chr(196).chr(168) => 'I', chr(196).chr(169) => 'i',
chr(196).chr(170) => 'I', chr(196).chr(171) => 'i',
chr(196).chr(172) => 'I', chr(196).chr(173) => 'i',
chr(196).chr(174) => 'I', chr(196).chr(175) => 'i',
chr(196).chr(176) => 'I', chr(196).chr(177) => 'i',
chr(196).chr(178) => 'IJ',chr(196).chr(179) => 'ij',
chr(196).chr(180) => 'J', chr(196).chr(181) => 'j',
chr(196).chr(182) => 'K', chr(196).chr(183) => 'k',
chr(196).chr(184) => 'k', chr(196).chr(185) => 'L',
chr(196).chr(186) => 'l', chr(196).chr(187) => 'L',
chr(196).chr(188) => 'l', chr(196).chr(189) => 'L',
chr(196).chr(190) => 'l', chr(196).chr(191) => 'L',
chr(197).chr(128) => 'l', chr(197).chr(129) => 'L',
chr(197).chr(130) => 'l', chr(197).chr(131) => 'N',
chr(197).chr(132) => 'n', chr(197).chr(133) => 'N',
chr(197).chr(134) => 'n', chr(197).chr(135) => 'N',
chr(197).chr(136) => 'n', chr(197).chr(137) => 'N',
chr(197).chr(138) => 'n', chr(197).chr(139) => 'N',
chr(197).chr(140) => 'O', chr(197).chr(141) => 'o',
chr(197).chr(142) => 'O', chr(197).chr(143) => 'o',
chr(197).chr(144) => 'O', chr(197).chr(145) => 'o',
chr(197).chr(146) => 'OE',chr(197).chr(147) => 'oe',
chr(197).chr(148) => 'R',chr(197).chr(149) => 'r',
chr(197).chr(150) => 'R',chr(197).chr(151) => 'r',
chr(197).chr(152) => 'R',chr(197).chr(153) => 'r',
chr(197).chr(154) => 'S',chr(197).chr(155) => 's',
chr(197).chr(156) => 'S',chr(197).chr(157) => 's',
chr(197).chr(158) => 'S',chr(197).chr(159) => 's',
chr(197).chr(160) => 'S', chr(197).chr(161) => 's',
chr(197).chr(162) => 'T', chr(197).chr(163) => 't',
chr(197).chr(164) => 'T', chr(197).chr(165) => 't',
chr(197).chr(166) => 'T', chr(197).chr(167) => 't',
chr(197).chr(168) => 'U', chr(197).chr(169) => 'u',
chr(197).chr(170) => 'U', chr(197).chr(171) => 'u',
chr(197).chr(172) => 'U', chr(197).chr(173) => 'u',
chr(197).chr(174) => 'U', chr(197).chr(175) => 'u',
chr(197).chr(176) => 'U', chr(197).chr(177) => 'u',
chr(197).chr(178) => 'U', chr(197).chr(179) => 'u',
chr(197).chr(180) => 'W', chr(197).chr(181) => 'w',
chr(197).chr(182) => 'Y', chr(197).chr(183) => 'y',
chr(197).chr(184) => 'Y', chr(197).chr(185) => 'Z',
chr(197).chr(186) => 'z', chr(197).chr(187) => 'Z',
chr(197).chr(188) => 'z', chr(197).chr(189) => 'Z',
chr(197).chr(190) => 'z', chr(197).chr(191) => 's'
);
$string = strtr($string, $chars);
return $string;
}
function escape_charaters($string) {
// $string = htmlentities($string);
$chars = array(
// superscript
chr(194).chr(185) => '1', chr(194).chr(178) => '2',
chr(194).chr(179) => '3', chr(226).chr(129).chr(180) => '4',
chr(226).chr(129).chr(181) => '5', chr(226).chr(129).chr(182) => '6',
chr(226).chr(129).chr(183) => '7', chr(226).chr(129).chr(184) => '8',
chr(226).chr(129).chr(185) => '9', chr(226).chr(129).chr(176) => '0',
// subscript
chr(226).chr(130).chr(129) => '1', chr(226).chr(130).chr(130) => '2',
chr(226).chr(130).chr(131) => '3', chr(226).chr(130).chr(132) => '4',
chr(226).chr(130).chr(133) => '5', chr(226).chr(130).chr(134) => '6',
chr(226).chr(130).chr(135) => '7', chr(226).chr(130).chr(136) => '8',
chr(226).chr(130).chr(137) => '9', chr(226).chr(130).chr(128) => '0',
// greek letters
chr(195).chr(134) => 'AE', chr(195).chr(166) => 'ae'
);
$string = strtr($string, $chars);
return $string;
// return html_entity_decode($string);
}
?>
urls);
}
// return a string of this object's parent url
// ish. not sure if this works very well.
// e.g, only works in browse, right?
public function back()
{
$urls = $this->urls;
array_pop($urls);
return implode("/", $urls);
}
}
?>