public function set($value, &$node) { if (empty($value) or !is_array($value)) { return; } switch ($value['error']) { case UPLOAD_ERR_OK: $value = Node::create('file')->import($value); break; case UPLOAD_ERR_INI_SIZE: throw new RuntimeException(t('Размер файла превышает установленное в системе ограничение (%size).', array('%size' => ini_get('upload_max_filesize')))); case UPLOAD_ERR_FORM_SIZE: throw new RuntimeException(t('Размер файла превышает установленное в форме ограничение.')); case UPLOAD_ERR_PARTIAL: throw new RuntimeException(t('Файл получен не полностью.')); case UPLOAD_ERR_NO_FILE: if (!empty($value['id']) and is_numeric($value['id'])) { $value = Node::load($value['id']); } elseif (!empty($value['url'])) { $value = FileNode::fromURL($value['url']); } elseif (!empty($value['ftp'])) { $value = Node::create('file')->importFromFTP(array_shift($value['ftp'])); } elseif (!empty($value['unlink'])) { $node->linkRemoveChild(null, $this->value); $value = null; } else { $value = $node->{$this->value}; } } if ($this->required and empty($value)) { throw new ValidationException($this->label, t('Вы не загрузили файл в поле «%name», хотя оно отмечено как обязательное.', array('%name' => mb_strtolower($this->label)))); } $node->{$this->value} = $value; }
public static function rpc_get_default(Context $ctx) { $user = Node::load(array('class' => 'user', 'deleted' => 0, 'published' => 1, 'id' => $ctx->get('id')), $ctx->db); $email = $user ? $user->email : '*****@*****.**'; $gurl = 'http://www.gravatar.com/avatar/' . md5($email); if (null !== ($s = $ctx->get('s'))) { $gurl .= '?s=' . intval($s) . '&r=x'; } return new Redirect($gurl); }
/** * Открепление файлов от ноды. */ public static function on_post_detach(Context $ctx) { if (is_array($ids = $ctx->post('remove'))) { $ctx->db->beginTransaction(); $params = array(); Node::load($ctx->get('id'), $ctx->db)->touch(ACL::UPDATE)->onSave('DELETE FROM `node__rel` WHERE `tid` = %ID% AND `key` IS NULL AND `nid` ' . sql::in($ids, $params), $params)->save(); $ctx->db->commit(); } return $ctx->getRedirect(); }
/** * Добавляет тип документа label. * * @mcms_message ru.molinos.cms.install */ public static function onInstall(Context $ctx) { try { $node = Node::load(array('class' => 'type', 'name' => 'label'), $ctx->db); } catch (ObjectNotFoundException $e) { $ctx->db->beginTransaction(); $node = Node::create(array('class' => 'type', 'name' => 'label', 'label' => t('Метка'), 'isdictionary' => true, 'fields' => array('name' => array('type' => 'TextLineControl', 'title' => t('Метка'), 'required' => true))), $ctx->db)->save(); $ctx->db->commit(); } }
public static function on_get_list(Context $ctx) { $xml = $ctx->db->getResult("SELECT `xmltree` FROM `node` WHERE `class` = 'tag' AND `parent_id` IS NULL"); if (empty($xml)) { $node = Node::load(array('class' => 'tag', 'deleted' => 0, 'parent_id' => null), $ctx->db); $xml = $node->getTreeXML(false, true); } $data = html::em('data', $xml); return html::em('content', array('edit' => true, 'nosearch' => true, 'name' => 'list', 'title' => t('Карта разделов сайта'), 'preset' => 'taxonomy'), $data); }
/** * Воссоздаёт контролы из БД. */ public static function rebuild(Database $db, $className) { try { $node = Node::load(array('class' => 'type', 'name' => $className, 'deleted' => 0), $db); $schema = (array) $node->fields; } catch (ObjectNotFoundException $e) { $schema = array(); } return $schema; }
/** * Инсталляция типа документа subscription. * * @mcms_message ru.molinos.cms.install */ public static function onInstall(Context $ctx) { try { $node = Node::load(array('class' => 'type', 'name' => 'subscription', 'deleted' => 0), $ctx->db); } catch (ObjectNotFoundException $e) { $ctx->db->beginTransaction(); $node = Node::create('type', array('name' => 'subscription', 'title' => t('Подписка на новости')))->save(); $ctx->db->commit(); } }
private static function getEmail(Context $ctx) { if ($id = $ctx->config->get('modules/admin/admin')) { try { $node = Node::load(array('id' => $id, 'class' => 'user')); return $node->getEmail(); } catch (ObjectNotFoundException $e) { } } }
/** * Обновление XML ноды и всех её связей. */ private static function update_node_xml(Node $node) { if ($ids = self::get_ids($node)) { $upd = $node->getDB()->prepare("UPDATE `node` SET `xml` = ? WHERE `id` = ?"); foreach ($ids as $id) { $upd->execute(array(Node::load($id, $node->getDB())->getXML(), $id)); Logger::log("node[{$id}]: XML updated", 'xml'); } } }
public function testLoadNode() { $id = get_test_context()->db->getResult("SELECT `id` FROM `node` WHERE `deleted` = 0 AND `class` = 'type' AND `name` = 'domain'"); $this->assertNotEquals(null, $id); $node = Node::load($id); $this->assertTrue($node instanceof Node); $this->assertEquals($id, $node->id); $this->assertEquals('type', $node->class); $this->assertEquals('domain', $node->name); }
public function __get($k) { if (!property_exists($this, $k)) { if (property_exists($this, 'ref_' . $k) && null !== $this->{'ref_' . $k}) { $this->{$k} = Node::load($this->{'ref_' . $k}); } else { $this->{$k} = null; } } return $this->{$k}; }
/** * @mcms_message ru.molinos.cms.install */ public static function on_install(Context $ctx) { try { $node = Node::load(array('class' => 'type', 'name' => 'tag', 'deleted' => 0), $ctx->db); } catch (ObjectNotFoundException $e) { $node = Node::create(array('class' => 'type', 'name' => 'tag', 'title' => t('Раздел'), 'fields' => array('name' => array('type' => 'TextLineControl', 'title' => t('Имя раздела'), 'required' => true))), $ctx->db); $node->getDB()->beginTransaction(); $node->save(); $node->getDB()->commit(); } }
public static function rpc_get_restore(Context $ctx) { $node = Node::load(array('class' => 'user', 'name' => $ctx->get('email'), 'deleted' => 0, 'published' => 1)); if ($ctx->get('otp') != $node->otp) { throw new ForbiddenException(t('Эта ссылка устарела.')); } $ctx->db->beginTransaction(); unset($node->otp); $node->save(); $ctx->db->commit(); $ctx->user->login($node->name, null, true); Logger::log($node->name . ' logged in using OTP.', 'auth'); }
/** * */ protected function editNode($node, $errors = array()) { $node = ARONode::finder()->byPK((int) $node); $this->tpl->assign('node', $node); $nodevalues = Node::load($node->id); $this->tpl->assign('values', !empty($_POST) ? (object) $_POST : $nodevalues); $this->tpl->assign('errors', $errors); $ct = $node->type; $ct->prepFields(); $this->tpl->assign('ct', $ct); $this->tpl->display('content/node_form.tpl.php'); // print_r($node); }
private static function updateXML($db) { $db->beginTransaction(); $upd = $db->prepare("UPDATE `node` SET `xml` = ? WHERE `id` = ?"); $sel = $db->exec("SELECT * FROM `node` WHERE `xml` IS NULL"); while ($row = $sel->fetch(PDO::FETCH_ASSOC)) { $id = $row['id']; unset($row['id']); unset($row['xml']); $node = Node::load($id, $db); $upd->execute(array($node->getXML(), $id)); } $db->commit(); }
/** * Переключение в контекст произвольного пользователя. * * Используется для отладки проблем, специфичных для пользователей. * Пользователь, в чей контекст нужно переключиться, указывается * в GET-параметрах "uid" или "username", числовой идентификатор * или логин, соответственно. * * При выходе из системы будет возвращена ранее активная сессия. * * Это действие доступно только отладчикам. * * @param Context $ctx используется для доступа к GET/POST данным. * @return string адрес перенаправления пользователя. */ public static function rpc_get_su(Context $ctx) { $user = Node::load(array('class' => 'user', 'deleted' => 0, 'id' => $ctx->get('id')), $ctx->db)->knock(ACL::CREATE); $curuid = $ctx->user->id; if ($user->id and $user->id != $curuid) { if (!is_array($stack = mcms::session('uidstack'))) { $stack = array(); } $stack[] = $curuid; mcms::session('uidstack', $stack); self::login($user->id); } return $ctx->getRedirect(); }
protected static function rpc_get_remove(Context $ctx) { $name = $ctx->get('name'); try { $node = Node::load(array('class' => 'subscription', 'name' => $name, 'deleted' => 0, 'published' => 1)); if (empty($node) or $node->id != $ctx->get('id')) { throw new PageNotFoundException(); } $ctx->db->beginTransaction(); $node->delete(); $ctx->db->commit(); } catch (ObjectNotFoundException $e) { } return $ctx->getRedirect('?unsubscribed=' . urlencode($name)); }
/** * Возвращает разделы, в которые можно помещать документы запрошенного типа. * Для типов документов всегда возвращает все разделы. */ public static function on_get_enabled(Context $ctx) { $node = Node::load($ctx->get('node'), $ctx->db); $filter = array('class' => 'tag', 'deleted' => 0); $options = array('multiple' => true); if ('type' != $node->class) { $type = Node::load(array('class' => 'type', 'name' => $node->class, 'deleted' => 0), $ctx->db); $filter['tagged'] = $type->id; if (!in_array($node->class, $ctx->config->getArray('modules/taxonomy/multitagtypes'))) { unset($options['multiple']); } $options['typeid'] = $type->id; } $filter['id'] = self::getPermittedSections($ctx); return new Response(html::em('nodes', $options, Node::findXML($filter, $ctx->db)), 'text/xml'); }
/** * Перемещает файл в S3. */ public static function on_move_to_s3(Context $ctx) { $node = Node::load($ctx->get('node'), $ctx->db); if (file_exists($fileName = $node->getRealURL())) { if ($url = self::moveFileToS3($fileName, null, $node->id . '/' . $node->filename)) { $ctx->db->beginTransaction(); $node->remoteurl = $url; $node->save(); $ctx->db->commit(); unlink($fileName); } } else { Logger::log('file not found: ' . $fileName, 's3'); } return $ctx->getRedirect(); }
/** * Клонирование объекта. * @route GET//api/node/clone.rpc */ public static function on_clone(Context $ctx) { $node = Node::load($ctx->get('id'))->knock(ACL::CREATE); $ctx->db->beginTransaction(); $node->published = false; $node->deleted = false; $node->created = null; $node->parent_id = $ctx->get('parent'); // Копируем связи с другими объектами. $node->onSave("REPLACE INTO `node__rel` (`tid`, `nid`, `key`) " . "SELECT %ID%, `nid`, `key` FROM `node__rel` WHERE `tid` = ?", array($node->id)); $node->onSave("REPLACE INTO `node__rel` (`tid`, `nid`, `key`) " . "SELECT `tid`, %ID%, `key` FROM `node__rel` WHERE `nid` = ?", array($node->id)); $ctx->registry->broadcast('ru.molinos.cms.node.clone', array($node)); $node->id = null; $node->save(); $node->updateXML(); $ctx->db->commit(); $ctx->redirect("admin/node/{$node->id}?destination=" . urlencode($ctx->get('destination'))); }
/** * Индексация документов, отсутствующих в индексе. */ private static function reindexMissingNodes(Context $ctx, Node $type) { $schema = Schema::load($ctx->db, $type->name); foreach ($schema->getIndexes() as $fieldName) { $tableName = 'node__idx_' . $fieldName; try { $ids = $ctx->db->getResultsV("id", "SELECT `id` FROM `node` WHERE `class` = ? AND `deleted` = 0 AND `id` NOT IN (SELECT `id` FROM `{$tableName}`)", array($type->name)); $upd = $ctx->db->prepare("INSERT INTO `{$tableName}` (`id`, `value`) VALUES (?, ?)"); $count = 0; foreach ((array) $ids as $nid) { $node = Node::load($nid, $ctx->db); $upd->execute(array($nid, $schema[$fieldName]->getIndexValue($node->{$fieldName}))); } } catch (TableNotFoundException $e) { Logger::log($e->getTableName() . ': missing table.'); } } }
/** * Сохранение раздела. * * При сохранении раздела с пустым полем parent_id, в него подставляется код * существующего корневого раздела (если он существует). Привязка к типам * документов копируется из родительского раздела. * * @return Node ссылка на себя (для построения цепочек). */ public function save() { $copyACL = false; if ($this->isNew()) { if (!$this->parent_id) { try { Node::load(array('class' => 'tag', 'parent_id' => null, 'deleted' => 0), $this->getDB()); throw new RuntimeException(t('Нельзя создать новый корневой раздел.')); } catch (ObjectNotFoundException $e) { } } // Копируем родительскую привязку к типам. $this->onSave("INSERT INTO `node__rel` (`tid`, `nid`, `key`, `order`) " . "SELECT %ID%, `nid`, `key`, `order` FROM `node__rel` " . "WHERE `tid` = ? AND `nid` IN (SELECT `id` FROM `node` WHERE `class` = 'type')", array($this->parent_id)); $copyACL = true; } parent::save(); if ($copyACL) { ACL::copyNode($this->parent_id, $this->id); } }
/** * Восстановление пароля. * * @param Context $ctx * @param array $params * @return void * @mcms_message ru.molinos.cms.auth.process.basicpw */ public static function on_register(Context $ctx, array $params) { if (false === strpos($params['email'], '@')) { throw new BadRequestException(t('Неверно введён почтовый адрес.')); } $node = Node::load(array('class' => 'user', 'name' => $params['email'])); if ($node->deleted) { throw new ForbiddenException(t('Этот пользователь был удалён.')); } elseif (!$node->published) { throw new ForbiddenException(t('Этот пользователь заблокирован.')); } $salt = md5($_SERVER['REMOTE_ADDR'] . microtime(true) . $node->name . rand()); $node->otp = $salt; $ctx->db->beginTransaction(); $node->save(); $ctx->db->commit(); $xml = html::em('request', array('email' => $node->name, 'host' => MCMS_HOST_NAME, 'base' => $ctx->url()->getBase($ctx), 'link' => 'authbasic/restore.rpc?email=' . urlencode($node->name) . '&otp=' . urlencode($salt))); $xsl = $ctx->config->get('modules/authbasic/restoretpl', os::path('lib', 'modules', 'authbasic', 'restore.xsl')); $html = xslt::transform($xml, $xsl, null); BebopMimeMail::send(null, $node->name, t('Восстановление пароля'), $html); }
private function notify($isnew) { if ($this->to and $this->to == Context::last()->user->id) { return; } $data = array('mode' => 'mail', 'node' => $this->getRaw()); $data['node']['uid'] = Node::load(array('class' => 'user', 'id' => $this->uid))->getRaw(); $message = bebop_render_object('mail', 'todo', null, $data, __CLASS__); if (!empty($message)) { if ($isnew) { if ($this->to) { mcms::mail(null, $this->to, t('Новое напоминание'), $message); } } elseif (!$isnew) { if ($this->closed) { mcms::mail(null, $this->uid, t('Напоминание удалено'), $message); } elseif ($this->to) { mcms::mail(null, $this->to, t('Напоминание реактивировано'), $message); } } } }
public function save() { if (empty($this->id)) { try { $dst = Node::load(array('class' => 'user', 'id' => $this->re)); if (!empty($dst->email)) { $email = $dst->email; } elseif (false !== strstr($dst->name, '@')) { $email = $dst->name; } if (!empty($email) and class_exists('BebopMimeMail')) { BebopMimeMail::send(null, $email, $this->name, $this->text); $this->data['sent'] = 1; } // Сохраняем в базе только если пользователь найден. // Чтобы можно было спокойно вызывать mcms::mail() для // любых объектов, не парясь с проверкой на class=user. return parent::save(); } catch (ObjectNotFoundException $e) { } } }
public function __construct(Context $ctx) { // Если кроме id аттачмента ничего не задали, ругаемся if (null == $ctx->get('fid', null) or null == $ctx->get('scale', null)) { $this->sendError(500, 'usage: ?q=imgtoolkit.rpc&fid=attachment[&operation=parameter...]'); } foreach ($this->options as $k => $v) { if ($p = $ctx->get($k)) { if (in_array($k, array('noshow', 'merge', 'fid', 'mirrorH', 'mirrorV'))) { $this->options[$k] = $p; } else { $this->options[$k] = floatval($p); } } // Формируем имя файла-ссылки для кэша $outfile .= "{$this->options[$k]},"; } $outfile = trim($outfile, ','); $node = Node::load(array('class' => 'file', 'id' => $this->options['fid'])); if (empty($node)) { self::sendError(404, 'attachment not found.'); } if (null === ($storage = mcms::config('filestorage'))) { $storage = 'storage'; } $this->node = $node; $this->filename = $node->filename; $this->folder = $storage; $this->sourceDir = $storage; $this->source = $storage . '/' . $node->filepath; $this->output = $this->folder . '/' . $outfile; if (null != $this->options['merge']) { $this->mergeNode = Node::load(array('class' => 'file', 'id' => $this->options['merge'])); if (empty($this->mergeNode)) { self::sendError(404, 'merge attachment not found.'); } } }
public static function hookRemoteCall(Context $ctx) { switch ($ctx->get('action')) { case 'add': $ctx->user->checkAccess(ACL::CREATE, 'todo'); $node = Node::create('todo', array('name' => $ctx->post('name'), 'uid' => $ctx->user->id, 'to' => $ctx->post('user', $ctx->user->id), 'published' => 1, 'rel' => $ctx->post('rel'))); if (empty($node->name)) { $msg = t('не указан текст задачи.'); bebop_on_json(array('status' => 'error', 'message' => $msg)); throw new InvalidArgumentException($msg); } $node->save(); bebop_on_json(array('status' => 'created', 'id' => $node->id, 'html' => $node->render())); break; case 'toggle': try { $node = Node::load(array('class' => 'todo', 'id' => $ctx->get('id'))); } catch (ObjectNotFoundException $e) { bebop_on_json(array('status' => 'error', 'message' => 'todo ' . $ctx->get('id') . ' not found')); throw new PageNotFoundException(); } if (empty($node->closed)) { $node->closed = date('Y-m-d H:i:s', time() - date('Z', time())); } else { $node->closed = null; } $node->save(); if ($ctx->method('POST') and null !== ($comment = $ctx->post('comment'))) { $tmp = Node::create('comment', array('uid' => $ctx->user->id, 'author' => $ctx->user->name, 'name' => t('Комментарий к напоминанию'), 'text' => $comment)); $tmp->save(); $tmp->linkAddParent($node->id); } $state = $node->closed ? 'closed' : 'open'; bebop_on_json(array('status' => 'ok', 'state' => $state)); break; } }
private static function getRecipients(Context $ctx) { $config = $ctx->config->get('modules/moderator'); $list = isset($config['super']) ? preg_split('/, */', $config['super']) : array(); if (Context::last()->user->id) { try { $tmp = Node::load(array('class' => 'user', 'id' => Context::last()->user->id)); if (!empty($tmp->publisher) and is_numeric($tmp->publisher)) { $tmp = Node::load(array('class' => 'user', 'id' => $tmp->publisher)); if (!empty($tmp->email)) { $list[] = $tmp->email; } } } catch (ObjectNotFoundException $e) { } } // Добавляем в список адреса, указанные в свойствах домена. if ($ctx = Context::last()) { if (isset($ctx->moderatoremail)) { $list += preg_split('/, */', $ctx->moderatoremail); } } return array_unique($list); }
public function set($value, &$node) { $this->validate($value); $fieldName = $this->value . '*'; $node->onSave("DELETE FROM `node__rel` WHERE `nid` = %ID% AND `key` = ?", array($fieldName)); if (empty($value)) { unset($node->{$this->value}); } else { $result = array(); $labels = preg_split('/,\\s*/', $value, -1, PREG_SPLIT_NO_EMPTY); foreach ($labels as $label) { try { $label = trim($label); $tmp = Node::load($f = array('class' => 'label', 'name' => $label, 'deleted' => 0), $node->getDB()); } catch (ObjectNotFoundException $e) { $tmp = Node::create(array('class' => 'label', 'name' => $label, 'published' => 1), $node->getDB())->save(); } $result[$tmp->id] = $tmp->name; } $params = array($fieldName); $node->onSave($sql = "INSERT INTO `node__rel` (`nid`, `tid`, `key`) SELECT %ID%, `id`, ? FROM `node` WHERE `class` = 'label' AND `id` " . sql::in(array_keys($result), $params), $params); $node->{$this->value} = $result; } }
/** * Диспетчер запросов. * * В зависимости от GET-параметра mode вызывает один из методов: onGetList() * или больше никакой. Гасит ошибки NoIndexException, возвращая вместо них * массив с ключём "error", значение которого содержит описание ошибки. * * @param array $options то, что насобирал getRequestOptions(). * * @return mixed то, что вернул конкретный метод-обработчик. */ public function onGet(array $options) { $count = null; $result = html::wrap('nodes', Node::findXML($query = $this->getQuery($options), $this->ctx->db)); // Пусто: откатываемся на другой раздел, но только если в текущем разделе // вообще ничего нет, на несуществующей странице выводим пустой список. if (empty($result)) { $count = $query->getCount($this->ctx->db); if (!$count and 'empty' == $this->fallbackmode and $this->fixed) { $options['section']['id'] = $this->fixed; $result = html::wrap('nodes', Node::findXML($query = $this->getQuery($options), $this->ctx->db)); $count = null; } } if (!empty($result)) { // Добавляем информацию о разделе. if ($this->showpath and !empty($options['section'])) { $tmp = ''; $section = Node::load($options['section'], $this->ctx->db); foreach ($section->getParents() as $node) { $tmp .= $node->push('section'); } if (!empty($tmp)) { $result .= html::em('path', $tmp); } } if ($this->pager and !empty($options['limit'])) { if (null === $count) { $count = $query->getCount($this->ctx->db); } $result .= $this->getPager($count, $options['page'], $options['limit']); } } return $result; }