public static function navMenu(&$user, $level = 1) { // FIXME: add exact match boolean for url/context checking $menu = array(); $context = null; $matches = array(); $requestUri = isset($_GET['uri']) ? $_GET['uri'] : isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : null; preg_match('#(/(.*))/((.*)(\\.php)?)#', $requestUri, $matches); $active = null; if (count($matches)) { $context = $matches[2]; $active = $matches[4]; } $paths = explode("/", $context); $db = Core::getDb(); $qLevel = $db->escape($level); $qContext = $db->escape($context); if ($context) { $q = "select title, url, level, admin, class, icon from menu_items where level={$qLevel} and ('{$qContext}' like concat('%', context, '%') or context is null) order by sortorder asc"; } else { $q = "select title, url, level, admin, class, icon from menu_items where level={$qLevel} and context is null order by sortorder asc"; } $rs = $db->query($q); if ($rs && $db->numRows($rs)) { while ($o = $db->fetchObject($rs)) { $menuItem = Boilerplate::navMenuItem($user, $o); if ($menuItem) { $menu[] = $menuItem; } } } return $menu; }
public function __construct($name, $logFacility = LOG_DAEMON) { $this->db = Core::getDb(); $this->name = $name; $this->logFacility = $logFacility; $this->pid = getmypid(); openlog("{$name}", LOG_PID, $this->logFacility); }
public static function store(&$email, $priority = 10) { $db = Core::getDb(); $q = $db->buildQuery("insert into mail_queue (msg_id, ctime, mtime, lock_id, priority, sent, subject, `from`, `to`, headers, body) values ('%s', now(), now(), null, %d, false, '%s', '%s', '%s', '%s', '%s')", $email->msgId(), $priority, $email->subject(), $email->from(), $email->to(), $email->headers(), $email->body()); $rs = $db->query($q); $id = $db->lastInsertId($rs); return $id; }
public static function show($objectId, $jsonLast = null) { $db = Core::getDb(); $user = Core::getUser(); $comments = array(); $qLast = $jsonLast ? "and c.id>" . $db->escape($jsonLast) : ""; $q = $db->buildQuery("SELECT c.id, c.body, o.ctime, u.id as local_user_id, o.user_id, c.user_connection_id, con.service, con.external_id\n FROM comments c\n LEFT JOIN objects o ON o.object_id=c.object_id\n LEFT JOIN connections con ON c.user_connection_id=con.id\n\t\t\tLEFT JOIN users u ON u.id=o.user_id\n WHERE c.in_reply_to_id=%d {$qLast}\n ORDER BY o.ctime ASC", $objectId); $rs = $db->query($q); if ($rs && $db->numrows($rs)) { while ($o = $db->fetchObject($rs)) { $commentAuthor = ObjectCache::getByType('\\Kiki\\User', $o->user_id ? $o->user_id : $o->local_user_id); if ($commentAuthor) { if ($o->external_id) { // HACK: should not always have to load this, but this is quicker than getStoredConnections for User 0 $connection = User\Factory::getInstance($o->service, $o->external_id, 0); // $connection = $commentAuthor->getConnection($o->service. "_". $o->external_id, true); if ($connection) { $serviceName = $connection->serviceName(); $name = $connection->name(); $pic = $connection->picture(); } else { $serviceName = 'None'; // SNH $name = $commentAuthor->name(); $pic = $commentAuthor->picture(); } } else { $serviceName = 'None'; // Kiki $name = $commentAuthor->name(); $pic = $commentAuthor->picture(); } } else { $serviceName = 'None'; $name = "Anonymous"; $pic = null; } if ($jsonLast !== null) { $comments[] = Comments::showSingle($objectId, $o->id, $name, $pic, $serviceName, $o->body, $o->ctime); } else { $comment = array('objectId' => $objectId, 'id' => $o->id, 'name' => $name, 'pic' => $pic, 'type' => $serviceName, 'body' => $o->body, 'ctime' => $o->ctime, 'dateTime' => date("c", strtotime($o->ctime)), 'relTime' => Misc::relativeTime($o->ctime)); $comments[] = $comment; } } } else { if ($jsonLast === null) { $comments[] = Comments::showDummy($objectId); } } if ($jsonLast !== null) { return $comments; } $template = new Template('parts/comments'); $template->assign('objectId', $objectId); $template->assign('comments', $comments); return $template->fetch(); }
public function __construct($id = 0, $objectId = 0) { $this->db = Core::getDb(); $this->id = $id; $this->objectId = $objectId; if ($this->id || $this->objectId) { $this->load(); } else { $this->reset(); } }
public function __construct(array $_data = array()) { if (!isset(self::$db)) { self::$db = Core::getDb(); } if (!isset(self::$request)) { self::$request = Core::$request; } if (!isset(self::$profile)) { self::$profile = Auth::$profile; self::$uid = self::$profile->user_id; } if (isset($_data)) { $this->_data = $_data; } }
public function __construct($template = null) { $this->db = Core::getDb(); $this->template = $template; $data = Core::getTemplateData(); // @deprecated Assign into global namespace. For backwards compatibility // with <= 0.0.32, when the namespace kiki was introduced and populated // but not yet ported and used. Compatibility will be removed in future // 0.1.0 (the this is getting somewhere update, which seems to be // approaching). foreach ($data as $key => $value) { switch ($key) { case 'config': break; default: $this->data[$key] = $value; } } // Assign to {$kiki} namespace. $this->data['kiki'] = $data; }
public static function articles($sectionId) { $db = Core::getDb(); $content = null; $articles = array(); $q = $db->buildQuery("select id from articles a LEFT JOIN objects o ON o.object_id=a.object_id where featured=true and visible=true and ctime<=now() and section_id=%d order by ctime desc limit 4", $sectionId); $rs = $db->query($q); if ($rs && ($count = $db->numRows($rs))) { while ($o = $db->fetchObject($rs)) { $article = new Article($o->id); $articles[] = $article; } } else { return $content; } $widths = array(); $widths[1] = array(780); $widths[2] = array(520, 260); $widths[3] = array(390, 195, 195); $widths[4] = array(195, 195, 195, 195); list($articles) = array_chunk($articles, 4); $count = count($articles); if (!$count) { return null; } $content .= "<div class=\"banner\">\n"; foreach ($articles as $id => $article) { $width = $widths[$count][$id]; $img = Storage::url($article->topImage()); list($base, $ext) = Storage::splitExtension($img); $img = "{$base}.{$width}x250.c.{$ext}"; $content .= "<div class=\"bannerItem\" style=\"width: {$width}px; background-image: url({$img});\">\n"; $content .= "<a href=\"" . $article->url() . "\">" . $article->title() . "</a>"; $content .= "</div>\n"; } $content .= "<br class=\"spacer\">"; $content .= "</div>\n"; return $content; }
public static function find($type = '', array $options = array()) { $where = $order = $joins = ''; if ($type && is_numeric($type)) { $options['conditions'] = ['id' => (int) $type]; $type = 'first'; } if (Core::$cache->exists('collections_' . get_called_class(), json_encode($options))) { // check if cached $result = Core::$cache->get('collections_' . get_called_class(), json_encode($options)); } else { $table = isset(static::$source) ? static::$source : strtolower(get_called_class()); if (isset($options['conditions']) && is_array($options['conditions'])) { $conditions = self::_mapConditions(self::_cleanOperators($options['conditions']), $table); $ac = []; foreach ($conditions as $k => $v) { if ($k === 'AND') { $ac['AND'][] = '(' . implode(' AND ', $v) . ')'; } else { if ($k === 'OR' && count($v) === 1) { $ac['OR'][] = "OR {$v['0']}"; } else { if ($k === 'OR') { $ac['AND'][] = '(' . implode(' OR ', $v) . ')'; } else { if ($k === 'MATCH' && count($v) === 1) { $ac['MATCH'][] = "{$v['0']}"; } else { if ($k === 'MATCH') { $ac['MATCH'][] = implode(' AND ', $v); } else { $ac['AND'][] = implode(' AND ', $v); } } } } } } if (!empty($ac)) { $where = ' WHERE'; } if (!empty($ac['MATCH'])) { $where .= ' ' . implode(' AND ', $ac['MATCH']) . ' AND'; } if (!empty($ac['AND'])) { $where .= ' ' . implode(' AND ', $ac['AND']); } if (!empty($ac['OR'])) { $where .= ' ' . implode(' OR ', $ac['OR']); } } if ($type == 'count') { $fields = 'COUNT(*) as count'; } else { $fields = '*'; if (isset($options['fields']) && is_array($options['fields'])) { $fields = []; foreach ($options['fields'] as $field) { $fields[] = strpos('.', $field) === false ? $table . '.' . $field : $field; } $fields = implode(",", $fields); } if (isset($options['order'])) { if (is_array($options['order'])) { $arr = []; foreach ($options['order'] as $key => $val) { if ($find = ucfirst(stristr($key, '.', true))) { $ok = class_exists($find) && isset($find::$source) ? $find::$source . stristr($key, '.') : strtolower($find) . stristr($key, '.'); } else { $ok = $table . '.' . $key; // default class name is table name } $arr[] = $ok . ' ' . $val; } $order = ' ORDER BY ' . implode(',', $arr); } } $limit = isset($options['limit']) && is_numeric($options['limit']) ? ' LIMIT ' . (int) $options['limit'] : ($type == 'first' ? ' LIMIT 1' : ''); $offset = isset($options['offset']) && is_numeric($options['offset']) && !empty($limit) ? ' OFFSET ' . (int) $options['offset'] : ''; } if (isset($options['joins']) && is_array($options['joins'])) { $joins = []; foreach ($options['joins'] as $model => $opts) { $model = property_exists($model, 'source') && isset($model::$source) ? $model::$source : strtolower($model); $constraints = self::_mapJoins(self::_mapConditions(self::_cleanOperators($opts['constraints']), $model)); $joins[] = ' INNER JOIN ' . $model . ' ' . $model . ' ON ' . $constraints; } $joins = implode(' ', $joins); } $sql = sprintf("SELECT %s FROM %s %s%s%s%s%s%s", $fields, $table, $table, $joins, $where, $order, $limit, $offset); error_log("sql: {$sql}"); if (isset($options['objects']) && $options['objects'] == false) { $result = Core::getDb()->sqlFetchAll($sql); } else { $rows = Core::getDb()->sqlFetchAll($sql); if (!empty($rows)) { $class = get_called_class(); if (count($rows) === 1) { // return 1 object $result = $class::create($rows[0]); } else { // return array of objects $result = []; foreach ($rows as $data) { $result[] = $class::create($data); } } } } Core::$cache->add('collections_' . get_called_class(), json_encode($options), $result); // cache it } return $result; }
/** * @return string database version or null when no value could be retrieved from the database. */ public static function dbVersion() { $db = Core::getDb(); $q = "select value from config where `key`='dbVersion'"; return $db->getSingleValue($q); }
/** * Stores a resource. * * @param string $fileName original filename * @param string $data file data * @return int ID of the database entry created */ public static function save($fileName, $data) { $db = Core::getDb(); $fileName = strtolower($fileName); // FIXME: care about actual mimetypes, not extensions $extension = self::getExtension($fileName); $hash = sha1(uniqid() . $data); $qHash = $db->escape($hash); $qName = $db->escape($fileName); $qExt = $db->escape($extension); $qSize = $db->escape(sizeof($data)); $q = "insert into storage(hash, original_name, extension, size) values('{$qHash}', '{$qName}', '{$qExt}', {$qSize})"; $rs = $db->query($q); $id = $db->lastInsertId($rs); $fileName = self::localFile($id); file_put_contents($fileName, $data); chmod($fileName, 0644); return $id; }
public function __construct() { $this->db = Core::getDb(); }
/** * Finds an album by title. Optionally creates a new album if none exists * by that title. * * @bug Only allows one album by title globally, this should be (at least) * on a per-user basis. * * @param string $title title of the album * @param boolean $create (optional) create a new album if none found, * defaults to false * * @return Album loaded instance when found/created, otherwise a bare * instance */ public static function findByTitle($title, $create = false) { $db = Core::getDb(); // Find $qTitle = $db->escape($title); $q = "select id from albums where title='{$qTitle}'"; $id = $db->getSingleValue($q); // Create if it doesn't exist if (!$id && $create) { $album = new Album(); $album->setTitle($title); $album->save(); return $album; } return new Album($id); }
/** * Retrieves the type of an object from the database. * * @param int $objectId * @return string Type (class name) of the object */ private static function getType($objectId) { $db = Core::getDb(); $q = $db->buildQuery("select type from objects where object_id=%d", $objectId); $type = $db->getSingleValue($q); // TODO: remove backwards compatibility return preg_match("/^Kiki\\\\/", $type) ? $type : 'Kiki\\' . $type; }
/** * Creates an article edit form. * * @fixme Should be integrated into a template. * @todo Traditional Page class is deprecated so we can now remove the $type argument hack and have a Page/Article class both deriving from Post. * * @param User $user User object, used to show the proper connection links for publications. * @param boolean $hidden Hide the form initially. * @param string $type Defaults to 'articles'. When set to 'page', form treats this article as a page. * * @return string The form HTML. * */ public function form($hidden = false, $type = 'articles') { $user = Core::getUser(); $date = date("d-m-Y H:i", $this->ctime ? strtotime($this->ctime) : time()); $class = $hidden ? "hidden" : ""; $sections = array(); if ($type == 'pages') { $sections[0] = 'top-level page'; } $db = Core::getDb(); $q = $db->buildQuery("select id,title from sections where type='%s' order by title asc", $type); $rs = $db->query($q); if ($rs && $db->numRows($rs)) { while ($oSection = $db->fetchObject($rs)) { $sections[$oSection->id] = $oSection->title; } } $content = Form::open("articleForm_" . $this->id, Config::$kikiPrefix . "/json/article.php", 'POST', $class, "multipart/form-data"); $content .= Form::hidden("articleId", $this->id); $content .= Form::hidden("albumId", $this->albumId); $content .= Form::select("sectionId", $sections, "Section", $this->sectionId); $this->loadPublications(); $content .= Form::text("title", $this->title, "Title"); if (!count($this->publications)) { $content .= Form::text("cname", $this->cname, "URL name"); } if ($type != 'pages') { $content .= Form::datetime("ctime", $date, "Date"); } $class = Config::$clEditor ? "cleditor" : null; $content .= Form::textarea("body", preg_replace('~\\r?\\n~', '
', htmlspecialchars($this->body)), "Body", null, 0, $class); if ($type != 'pages') { $content .= Form::checkbox("featured", $this->featured, "Featured"); } $content .= Form::checkbox("visible", $this->visible, "Visible"); $content .= "<label>Publications</label>"; foreach ($this->publications as $publication) { $content .= "<a href=\"" . $publication->url() . "\" class=\"button\"><span class=\"buttonImg " . $publication->service() . "\"></span>" . $publication->service() . "</a>\n"; } // TODO: Make this generic, difference with social update is the check // against an already stored external URL. foreach ($user->connections() as $connection) { if ($connection->serviceName() == 'Facebook') { // TODO: inform user that, and why, these are required. if (!$connection->hasPerm('publish_stream')) { continue; } $content .= Form::checkbox("connections[" . $connection->uniqId() . "]", false, $connection->serviceName(), $connection->name()); } else { if ($connection->serviceName() == 'Twitter') { $content .= Form::checkbox("connections[" . $connection->uniqId() . "]", false, $connection->serviceName(), $connection->name()); $content .= Form::text("hashtags", $this->hashtags, "Hashtags"); } } } $content .= Form::button("submit", "submit", "Opslaan"); $content .= Form::close(); return $content; }
public static function storeBaseUri($baseUri, $title, $type, $instanceId = 0) { $db = Core::getDb(); if ($baseUri[0] != '/') { $baseUri = '/' . $baseUri; } $q = $db->buildQuery("INSERT INTO sections (id, base_uri, title, type) VALUES (%d, '%s', '%s', '%s') ON DUPLICATE KEY UPDATE type='%s', title='%s'", $instanceId, $baseUri, $title, $type, $type, $title); $db->query($q); }
public static function albumImage($id, $label, $albumId, $selected = 0) { $db = Core::getDb(); $template = new Template('forms/album-selectimage'); $imgUrl = $selected ? Storage::url($selected, 75, 75, true) : "/kiki/img/blank.gif"; $template->assign('label', $label); $template->assign('imgUrl', $imgUrl); $images = array(); $q = $db->buildQuery("select p.storage_id from pictures p, album_pictures ap where ap.picture_id=p.id AND ap.album_id=%d", $albumId); $rs = $db->query($q); if ($rs && $db->numRows($rs)) { while ($o = $db->fetchObject($rs)) { $url = Storage::url($o->storage_id, 75, 75, true); $images[] = array('storageId' => $o->storage_id, 'url' => $url); } } $template->assign('images', $images); $template->assign('id', $id); $template->assign('selected', $selected); return $template->fetch(); }
/** @TODO Figure out what the f**k I mean when I say "of note." */ protected function disconnect() { /** @TODO Add more Core hook functionality here and elsewhere. */ /** Check to ensure the driver has been loaded and let it connect. */ if (!isset($this->driver)) { $this->loadDriver(); } /** If this model instance is not connected do nothing (may wanna log this). */ if (!isset($this->connection)) { return; } /** Use the default db config unless another is defined within the model. */ $this->db = isset($this->db) ? $this->db : Core::getDb(); /** Return the associated connection object result. */ $this->connection = $this->driver->disconnect($this); }