Working on Web admin

This commit is contained in:
Jérôme Schneider 2012-04-04 14:05:13 +02:00
parent c6dcd12d44
commit 1a268588b3
29 changed files with 472 additions and 153 deletions

View file

@ -58,6 +58,13 @@ define("BAIKAL_PATH_WWWROOT", BAIKAL_PATH_CORE . "WWWRoot/");
require_once(BAIKAL_PATH_SPECIFIC . "config.php");
require_once(BAIKAL_PATH_SPECIFIC . "config.system.php");
# Determining baikal protocol, domain and uri-path (looking at BAIKAL_URI)
$aUrlInfo = parse_url(BAIKAL_URI);
define("BAIKAL_DOMAIN", $aUrlInfo["host"]);
define("BAIKAL_URIPROTOCOL", $aUrlInfo["scheme"]);
define("BAIKAL_URIPATH", $aUrlInfo["path"]);
date_default_timezone_set(BAIKAL_TIMEZONE);
# Check if DB exists

View file

@ -9,6 +9,7 @@ class User extends \Flake\Core\Model\Db {
protected $aData = array(
"username" => "",
"digesta1" => "",
);
protected $oIdentityPrincipal = null;
@ -31,6 +32,12 @@ class User extends \Flake\Core\Model\Db {
}
public function get($sPropName) {
if($sPropName === "password" || $sPropName === "passwordconfirm") {
# Special handling for password and passwordconfirm
return "";
}
try {
# does the property exist on the model object ?
$sRes = parent::get($sPropName);
@ -43,6 +50,20 @@ class User extends \Flake\Core\Model\Db {
}
public function set($sPropName, $sPropValue) {
if($sPropName === "password" || $sPropName === "passwordconfirm") {
# Special handling for password and passwordconfirm
if($sPropName === "password" && $sPropValue !== "") {
parent::set(
"digesta1",
$this->getPasswordHashForPassword($sPropValue)
);
}
return $this;
}
try {
# does the property exist on the model object ?
parent::set($sPropName, $sPropValue);
@ -60,9 +81,7 @@ class User extends \Flake\Core\Model\Db {
$this->oIdentityPrincipal->set("uri", "principals/" . $this->get("username"));
$this->oIdentityPrincipal->persist();
if($this->floating()) {
parent::persist();
}
parent::persist();
}
public function destroy() {
@ -92,7 +111,7 @@ class User extends \Flake\Core\Model\Db {
$oMorpho->add(new \Formal\Element\Text(array(
"prop" => "username",
"label" => "Username",
"validation" => "required"
"validation" => "required,unique"
)));
$oMorpho->add(new \Formal\Element\Text(array(
@ -107,8 +126,25 @@ class User extends \Flake\Core\Model\Db {
"validation" => "required,email"
)));
if(!$this->floating()) {
$oMorpho->add(new \Formal\Element\Password(array(
"prop" => "password",
"label" => "Password",
)));
$oMorpho->add(new \Formal\Element\Password(array(
"prop" => "passwordconfirm",
"label" => "Confirm password",
"validation" => "sameas:password",
)));
if($this->floating()) {
$oMorpho->element("password")->setOption("validation", "required");
} else {
$sNotice = "-- Leave empty to keep current password --";
$oMorpho->element("username")->setOption("readonly", true);
$oMorpho->element("password")->setOption("placeholder", $sNotice);
$oMorpho->element("passwordconfirm")->setOption("placeholder", $sNotice);
}
return $oMorpho;
@ -117,4 +153,8 @@ class User extends \Flake\Core\Model\Db {
public static function getIcon() {
return "icon-user";
}
public function getPasswordHashForPassword($sPassword) {
return md5($this->get("username") . ':' . BAIKAL_AUTH_REALM . ':' . $sPassword);
}
}

View file

@ -0,0 +1,24 @@
<?php
namespace BaikalAdmin\Controler;
class Dashboard extends \Flake\Core\Controler {
function execute() {
}
function render() {
$sLinkUsers = \BaikalAdmin\Controler\Users::link();
$sMessage =<<<MESSAGE
Ici, infos sur:<br />
* Nombre d'utilisateurs<br />
* Nombre de calendriers<br />
* Nombre d'évènements<br />
* Version + Mise à jour de baikal<br />
* <a href='{$sLinkUsers}'>Lien vers liste des utilisateurs</a><br />
* Lien vers paramétrage<br />
MESSAGE;
return $sMessage;
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace BaikalAdmin\Controler;
class Details extends \Flake\Core\Controler {
function execute() {
}
function render() {
return "<h2>Details !</h2>";
}
}

View file

@ -0,0 +1,13 @@
<?php
namespace BaikalAdmin\Controler;
class Install extends \Flake\Core\Controler {
function execute() {
}
function render() {
return "<h2>Install</h2>";
}
}

View file

@ -1,21 +0,0 @@
<?php
namespace BaikalAdmin\Controler\User;
class Listing extends \Flake\Core\Controler {
function execute() {
}
function render() {
$aRes = array();
$oUsers = \Baikal\Model\User::getBaseRequester()
->execute();
$oView = new \BaikalAdmin\View\User\Listing();
$oView->setData("users", $oUsers);
return $oView->render();
}
}

View file

@ -1,8 +1,8 @@
<?php
namespace BaikalAdmin\Controler\User;
namespace BaikalAdmin\Controler;
class Form extends \Flake\Core\Controler {
class Users extends \Flake\Core\Controler {
const BASEPATH = "/admin/";
protected $aMessages = array();
@ -60,7 +60,7 @@ class Form extends \Flake\Core\Controler {
}
# Redirecting to admin home
\Flake\Util\Tools::redirectUsingMeta(self::BASEPATH);
\Flake\Util\Tools::redirectUsingMeta(self::link());
} else {
$oUser = new \Baikal\Model\User($iUser);
@ -69,7 +69,7 @@ class Form extends \Flake\Core\Controler {
"<p>You are about to delete a user and all it's calendars / contacts. This operation cannot be undone.</p><p>So, now that you know all that, what shall we do ?</p>",
self::linkDeleteConfirm($oUser),
"Delete <strong><i class='" . $oUser->getIcon() . " icon-white'></i> " . $oUser->getLabel() . "</strong>",
self::BASEPATH
self::link()
);
}
}
@ -78,7 +78,7 @@ class Form extends \Flake\Core\Controler {
function initForm() {
if($this->editRequested() || $this->newRequested()) {
$aOptions = array(
"closeurl" => $this::BASEPATH
"closeurl" => self::link()
);
$this->oForm = $this->oModel->formForThisModelInstance($aOptions);
@ -86,16 +86,18 @@ class Form extends \Flake\Core\Controler {
}
public static function editRequested() {
if(($iUser = intval(\Flake\Util\Tools::GET("useredit"))) > 0) {
return $iUser;
$aParams = $GLOBALS["ROUTER"]::getURLParams();
if(($aParams[0] === "edit") && intval($aParams[1]) > 0) {
return intval($aParams[1]);
}
return FALSE;
}
public static function deleteRequested() {
if(($iUser = intval(\Flake\Util\Tools::GET("userdel"))) > 0) {
return $iUser;
$aParams = $GLOBALS["ROUTER"]::getURLParams();
if(($aParams[0] === "delete") && intval($aParams[1]) > 0) {
return intval($aParams[1]);
}
return FALSE;
@ -106,7 +108,8 @@ class Form extends \Flake\Core\Controler {
return FALSE;
}
if(intval(\Flake\Util\tools::GET("userdelconfirm")) === 1) {
$aParams = $GLOBALS["ROUTER"]::getURLParams();
if($aParams[2] === "confirm") {
return $iUser;
}
@ -114,12 +117,22 @@ class Form extends \Flake\Core\Controler {
}
public static function newRequested() {
return (intval(\Flake\Util\Tools::GET("usernew")) === 1);
$aParams = $GLOBALS["ROUTER"]::getURLParams();
return $aParams[0] === "new";
}
function render() {
$sHtml = "";
$sHtml = "<a id='edituser'></a>";
# Render list of users
$oUsers = \Baikal\Model\User::getBaseRequester()->execute();
$oView = new \BaikalAdmin\View\User\Listing();
$oView->setData("users", $oUsers);
$sHtml .= $oView->render();
# Render form
$sHtml .= "<a id='edituser'></a>";
$sMessages = implode("\n", $this->aMessages);
if(($iUser = self::editRequested()) !== FALSE) {
@ -143,23 +156,27 @@ class Form extends \Flake\Core\Controler {
return $sHtml;
}
public static function link() {
return BAIKAL_URI . BAIKALADMIN_URIPATH . $GLOBALS["ROUTER"]::buildRouteForControler("\BaikalAdmin\Controler\Users");
}
public static function linkNew() {
return self::BASEPATH . "?usernew=1#edituser";
return BAIKAL_URI . BAIKALADMIN_URIPATH . $GLOBALS["ROUTER"]::buildCurrentRoute("new") . "#edituser";
}
public static function linkEdit(\Baikal\Model\User $user) {
return self::BASEPATH . "?useredit=" . $user->get("id") . "#edituser";
return BAIKAL_URI . BAIKALADMIN_URIPATH . $GLOBALS["ROUTER"]::buildCurrentRoute("edit", $user->get("id")) . "#edituser";
}
public static function linkDelete(\Baikal\Model\User $user) {
return self::BASEPATH . "?userdel=" . $user->get("id") . "#confirm";
return BAIKAL_URI . BAIKALADMIN_URIPATH . $GLOBALS["ROUTER"]::buildCurrentRoute("delete", $user->get("id")) . "#message";
}
public static function linkDeleteConfirm(\Baikal\Model\User $user) {
return self::BASEPATH . "?userdel=" . $user->get("id") . "&userdelconfirm=1#confirm";
return BAIKAL_URI . BAIKALADMIN_URIPATH . $GLOBALS["ROUTER"]::buildCurrentRoute("delete", $user->get("id"), "confirm") . "#message";
}
public static function linkDetails(\Baikal\Model\User $user) {
return self::BASEPATH . "?userdetails=" . $user->get("id") . "#confirm";
return BAIKAL_URI . BAIKALADMIN_URIPATH . $GLOBALS["ROUTER"]::buildCurrentRoute("details", $user->get("id"));
}
}

View file

@ -15,5 +15,7 @@ require_once(dirname(dirname(dirname(__FILE__))) . "/Formal/Core/Bootstrap.php")
require_once(dirname(__FILE__) . '/ClassLoader.php');
\BaikalAdmin\Core\ClassLoader::register();
define("BAIKALADMIN_URIPATH", \Flake\Util\Tools::trimSlashes(dirname($_SERVER["SCRIPT_NAME"])) . "/");
# Include BaikalAdmin Framework config
require_once(BAIKALADMIN_PATH_ROOT . "config.php");

View file

@ -7,7 +7,7 @@
<header class="jumbotron subhead" id="overview">
<h1>Users</h1>
<p class="lead pull-left">Browse, create, update and delete Baïkal user accounts.</p>
<p class="pull-right"><a class="btn" href="<?= \BaikalAdmin\Controler\User\Form::linkNew() ?>"><i class="<?= \Baikal\Model\User::getIcon() ?>"></i> + Add user</a></p>
<p class="pull-right"><a class="btn" href="<?= \BaikalAdmin\Controler\Users::linkNew() ?>"><i class="<?= \Baikal\Model\User::getIcon() ?>"></i> + Add user</a></p>
</header>
<table class="table table-bordered table-striped">
@ -17,9 +17,9 @@
<th class="col-actions no-border-left"></th>
</tr-->
<? foreach($users as $user) {
$linkdetails = \BaikalAdmin\Controler\User\Form::linkDetails($user);
$linkedit = \BaikalAdmin\Controler\User\Form::linkEdit($user);
$linkdelete = \BaikalAdmin\Controler\User\Form::linkDelete($user);
$linkdetails = \BaikalAdmin\Controler\Users::linkDetails($user);
$linkedit = \BaikalAdmin\Controler\Users::linkEdit($user);
$linkdelete = \BaikalAdmin\Controler\Users::linkDelete($user);
$mailtouri = $user->getMailtoURI();
?>
<tr>

View file

@ -0,0 +1,10 @@
<?php
namespace BaikalAdmin\Route;
class Dashboard {
public static function execute(\Flake\Core\Render\Container &$oRenderContainer) {
$oRenderContainer->zone("Payload")->addBlock(new \BaikalAdmin\Controler\Dashboard());
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace BaikalAdmin\Route;
class Details {
public static function execute(\Flake\Core\Render\Container &$oRenderContainer) {
$oRenderContainer->zone("Payload")->addBlock(new \BaikalAdmin\Controler\Details());
}
}

View file

@ -0,0 +1,10 @@
<?php
namespace BaikalAdmin\Route;
class Install {
public static function execute(\Flake\Core\Render\Container &$oRenderContainer) {
$oRenderContainer->zone("Payload")->addBlock(new \BaikalAdmin\Controler\Install());
}
}

View file

@ -5,7 +5,6 @@ namespace BaikalAdmin\Route;
class Users {
public static function execute(\Flake\Core\Render\Container &$oRenderContainer) {
$oRenderContainer->zone("Payload")->addBlock(new \BaikalAdmin\Controler\User\Listing());
$oRenderContainer->zone("Payload")->addBlock(new \BaikalAdmin\Controler\User\Form());
$oRenderContainer->zone("Payload")->addBlock(new \BaikalAdmin\Controler\Users());
}
}

View file

@ -9,8 +9,8 @@ class Form extends \Flake\Core\View {
return $oTemplate->parse(array(
"user" => $oUser,
"linkcancel" => \BaikalAdmin\Controler\User\Form::BASEPATH,
"action" => \BaikalAdmin\Controler\User\Form::linkEdit($oUser),
"linkcancel" => \BaikalAdmin\Controler\Users::link(),
"action" => \BaikalAdmin\Controler\Users::linkEdit($oUser),
"messages" => $this->get("messages"),
));
}

View file

@ -3,5 +3,8 @@
define("BAIKALADMIN_PATH_TEMPLATES", BAIKALADMIN_PATH_ROOT . "Resources/Templates/");
$GLOBALS["ROUTES"] = array(
"default" => "\BaikalAdmin\Route\Users",
"default" => "\BaikalAdmin\Route\Dashboard",
"users" => "\BaikalAdmin\Route\Users",
"users/details" => "\BaikalAdmin\Route\Details",
"install" => "\BaikalAdmin\Route\Install"
);

View file

@ -29,10 +29,9 @@ error_reporting(E_ALL);
define("BAIKAL_CONTEXT", TRUE);
define("BAIKAL_CONTEXT_ADMIN", TRUE);
define("PATH_ENTRYDIR", dirname(__FILE__) . "/");
# Bootstrap BaikalAdmin
require_once(PATH_ENTRYDIR . "Core/Bootstrap.php");
require_once(dirname(__FILE__) . "/Core/Bootstrap.php");
# Evaluate assertions
\BaikalAdmin\Core\Auth::assertEnabled();
@ -45,7 +44,7 @@ $oPage->setTitle(FLAKE_BASEURL);
$oPage->setBaseUrl(FLAKE_BASEURL);
# Route the request
\Flake\Util\Router::route($oPage);
$GLOBALS["ROUTER"]::route($oPage);
# Render the page
echo $oPage->render();

View file

@ -28,6 +28,9 @@ require_once(FLAKE_PATH_ROOT . 'Core/ClassLoader.php');
# Include Flake Framework config
require_once(FLAKE_PATH_ROOT . "config.php");
# Determine Router class
$GLOBALS["ROUTER"] = \Flake\Util\Tools::router();
if(!\Flake\Util\Tools::isCliPhp()) {
ini_set("html_errors", TRUE);
session_start();

View file

@ -13,10 +13,10 @@ abstract class Controler extends \Flake\Core\FLObject {
abstract function execute();
abstract function render();
public static function buildRouteWithParams() {
public static function buildRoute(/*[$sParam, $sParam2, ...]*/) {
$aParams = func_get_args();
$sControler = "\\" . get_called_class();
array_unshift($aParams, $sControler);
return call_user_func_array("\Flake\Util\Router::buildRouteForControlerWithParams", $aParams);
array_unshift($aParams, $sControler); # Injecting current controler as first param
return call_user_func_array($GLOBALS["ROUTER"] . "::buildRouteForControler", $aParams);
}
}

View file

@ -2,36 +2,22 @@
namespace Flake\Util;
class Router extends \Flake\Core\FLObject {
abstract class Router extends \Flake\Core\FLObject {
public static function getCurrentRoute() {
$sUrl = trim($GLOBALS["_SERVER"]["REDIRECT_URL"]);
if($sUrl{0} === "/") {
$sUrl = substr($sUrl, 1);
}
if($sUrl{strlen($sUrl) - 1} === "/") {
$sUrl = substr($sUrl, 0, -1);
}
$aParts = explode("/", $sUrl);
$sRoute = $aParts[0];
if(trim($sUrl) === "") {
$sRoute = "default";
} else {
if(!array_key_exists($sRoute, $GLOBALS["ROUTES"])) {
$sRoute = "default";
}
}
return $sRoute;
/* ----------------------- COMMON METHODS ------------------------------*/
private function __construct() {
# private constructor for static class
}
public static function getControlerForRoute($sRoute) {
return $GLOBALS["ROUTES"][$sRoute];
public static function getRoutes() {
reset($GLOBALS["ROUTES"]);
return $GLOBALS["ROUTES"];
}
public static function getControlerForRoute($sRoute) {
$aRoutes = $GLOBALS["ROUTER"]::getRoutes();
return $aRoutes[$sRoute];
}
public static function getRouteForControler($sControler) {
@ -40,9 +26,11 @@ class Router extends \Flake\Core\FLObject {
$sControler = "\\" . $sControler;
}
reset($GLOBALS["ROUTES"]);
while(list($sRoute,) = each($GLOBALS["ROUTES"])) {
if(str_replace("\\Route", "\\Controler", $GLOBALS["ROUTES"][$sRoute]) === $sControler) {
$aRoutes = $GLOBALS["ROUTER"]::getRoutes();
reset($aRoutes);
while(list($sRoute,) = each($aRoutes)) {
if(str_replace("\\Route", "\\Controler", $aRoutes[$sRoute]) === $sControler) {
return $sRoute;
}
}
@ -51,28 +39,46 @@ class Router extends \Flake\Core\FLObject {
}
public static function route(\Flake\Core\Render\Container &$oRenderContainer) {
$sControler = self::getControlerForRoute(
self::getCurrentRoute()
$sControler = $GLOBALS["ROUTER"]::getControlerForRoute(
$GLOBALS["ROUTER"]::getCurrentRoute()
);
$sControler::execute($oRenderContainer);
}
public static function buildRouteForControlerWithParams() {
public static function buildRouteForControler($sControler /* [, $sParam, $sParam2, ...] */) {
$aParams = func_get_args();
$sControler = array_shift($aParams);
$sRouteForControler = self::getRouteForControler($sControler);
return "/" . $sRouteForControler . "/" . implode("/", $aParams);
array_shift($aParams); # stripping $sControler
$sRouteForControler = $GLOBALS["ROUTER"]::getRouteForControler($sControler);
array_unshift($aParams, $sRouteForControler); # Injecting route as first param
return call_user_func_array($GLOBALS["ROUTER"] . "::buildRoute", $aParams);
}
/* public static function buildRouteWithParams() {
public static function buildCurrentRoute(/*[$sParam, $sParam2, ...]*/) {
$aParams = func_get_args();
$sCurrentRoute = $GLOBALS["ROUTER"]::getCurrentRoute();
list(, $aCall) = debug_backtrace(FALSE);
$sClass = $aCall["class"];
$sClass = str_replace("\\Route", "", $sClass);
array_unshift($aParams, $sCurrentRoute); # Injecting route as first param
return call_user_func_array($GLOBALS["ROUTER"] . "::buildRoute", $aParams);
}
/* ----------------------- CHANGING METHODS ----------------------------*/
# this method is likely to change with every Router implementation
public static function buildRoute($sRoute /* [, $sParam, $sParam2, ...] */) {
$aParams = func_get_args();
array_shift($aParams); # Stripping $sRoute
$sRouteForControler = self::getRouteForControler($sClass);
return "/" . $sRouteForControler . "/" . implode("/", $aParams);
}*/
$sParams = implode("/", $aParams);
if(trim($sParams) !== "") {
$sParams .= "/";
}
return "/" . $sRoute . "/" . $sParams;
}
public static abstract function getCurrentRoute();
public static abstract function getURLParams();
}

View file

@ -0,0 +1,65 @@
<?php
namespace Flake\Util\Router;
class QuestionMarkRewrite extends \Flake\Util\Router {
public static function getCurrentRoute() {
$sUrl = \Flake\Util\Tools::trimSlashes($GLOBALS["_SERVER"]["REQUEST_URI"]); # REDIRECT_URL for ServerRewrite
$sScriptDir = \Flake\Util\Tools::appendSlash(dirname($GLOBALS["_SERVER"]["SCRIPT_NAME"]));
if(trim($sUrl) === "") {
return "default";
} else {
$aURI = parse_url($sUrl);
$sRoutePart = \Flake\Util\Tools::stripBeginSlash($aURI["query"]);
$aMatches = array();
$aRoutes = self::getRoutes();
reset($aRoutes);
foreach($aRoutes as $sDefinedRoute => $sDefinedControler) {
if(strpos($sRoutePart, $sDefinedRoute) !== FALSE) {
# found a match
$iSlashCount = substr_count($sDefinedRoute, "/");
if(!array_key_exists($iSlashCount, $aMatches)) {
$aMatches[$iSlashCount] = array();
}
$aMatches[$iSlashCount][] = $sDefinedRoute;
}
}
if(empty($aMatches)) {
return "default";
}
$aBestMatches = array_pop($aMatches); // obtains the deepest matching route (higher number of slashes)
return array_shift($aBestMatches); // first route amongst best matches
}
return $sRoute;
}
public static function buildRoute(/* undetermined number of parameters */) {
$aParams = func_get_args();
$sUrl = call_user_func_array("parent::buildRoute", $aParams);
return "?" . $sUrl;
}
public static function getURLParams() {
$aTokens = \Flake\Util\Tools::getUrlTokens();
# stripping route and "?" tokens
if(($iPosQuestionMark = array_search("?", $aTokens)) !== FALSE) {
# Pos+0 = position of "?"
# Pos+1 = position of "route"
# Pos+2 = position of first param
return array_slice($aTokens, $iPosQuestionMark + 2);
}
return array();
}
}

View file

@ -9,11 +9,8 @@ class Tools extends \Flake\Core\FLObject {
}
public static function getUrlTokens() {
$sUrl = self::getCurrentUrl();
if($sUrl{0} === "/") {
$sUrl = substr($sUrl, 1);
}
$sUrl = self::stripBeginSlash(self::getCurrentUrl());
if(trim($sUrl) !== "") {
return explode("/", $sUrl);
}
@ -31,10 +28,6 @@ class Tools extends \Flake\Core\FLObject {
return str_replace($sSep, $sGlue, $sRes);
}
public static function getAction() {
return \Flake\Util\Tools::GET("action");
}
public static function absolutizeURL($sUrl) {
$aUrl = parse_url($sUrl);
if($aUrl["scheme"] !== "http" && $aUrl["scheme"] !== "https") {
@ -589,4 +582,44 @@ TEST;
public static function getUserAgent() {
return $_SERVER['HTTP_USER_AGENT'];
}
public static function appendSlash($sString) {
if(substr($sString, -1) !== "/") {
$sString .= "/";
}
return $sString;
}
public static function prependSlash($sString) {
if(substr($sString, 0, 1) !== "/") {
$sString = "/" . $sString;
}
return $sString;
}
public static function stripBeginSlash($sString) {
if(substr($sString, 0, 1) === "/") {
$sString = substr($sString, 1);
}
return $sString;
}
public static function stripEndSlash($sString) {
if(substr($sString, -1) === "/") {
$sString = substr($sString, 0, -1);
}
return $sString;
}
public static function trimSlashes($sString) {
return self::stripBeginSlash(self::stripEndSlash($sString));
}
public static function router() {
return "\Flake\Util\Router\QuestionMarkRewrite";
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace Formal;
class Core {
public static function handle($sName) {
debug("Handling " . $sName);
}
}

View file

@ -5,13 +5,15 @@ namespace Formal;
class Element {
protected $aOptions = array(
"readonly" => FALSE,
"validation" => "",
"error" => FALSE,
"placeholder" => "",
);
protected $sValue = "";
public function __construct($aOptions) {
$this->aOptions = array_merge($aOptions, $this->aOptions);
$this->aOptions = array_merge($this->aOptions, $aOptions);
}
public function option($sName) {
@ -22,10 +24,12 @@ class Element {
throw new \Exception("\Formal\Element->option(): Option '" . htmlspecialchars($sName) . "' not found.");
}
public function optionArray($sName) {
$sOption = trim($this->option($sName));
public function optionArray($sOptionName) {
$sOption = trim($this->option($sOptionName));
if($sOption !== "") {
$aOptions = explode(",", $sOption);
} else {
$aOptions = array();
}
reset($aOptions);
@ -36,6 +40,12 @@ class Element {
$this->aOptions[$sOptionName] = $sOptionValue;
}
/* public function addToOptionArray($sOptionName, $sOptionValue) {
$aOptions = $this->optionArray($sOptionName);
$aOptions[] = $sOptionValue;
$this->aOptions[$sOptionName] = implode(",", $aOptions);
}*/
public function value() {
return $this->sValue;
}

View file

@ -0,0 +1,41 @@
<?php
namespace Formal\Element;
class Password extends \Formal\Element {
public function render() {
$disabled = "";
$inputclass = "";
$groupclass = "";
$placeholder = "";
$value = htmlspecialchars($this->value());
$label = $this->option("label");
$prop = $this->option("prop");
$placeholder = $this->option("placeholder");
if($this->option("readonly") === TRUE) {
$inputclass .= " disabled";
$disabled = " disabled";
}
if($this->option("error") === TRUE) {
$groupclass .= " error";
}
if(($sPlaceHolder = trim($this->option("placeholder"))) !== "") {
$placeholder = " placeholder=\"" . htmlspecialchars($sPlaceHolder) . "\" ";
}
$sHtml =<<<HTML
<div class="control-group{$groupclass}">
<label class="control-label" for="displayname">{$label}</label>
<div class="controls">
<input type="password" class="input-xlarge{$inputclass}" id="{$prop}" name="{$prop}" value="{$value}"{$disabled}{$placeholder}/>
</div>
</div>
HTML;
return $sHtml;
}
}

View file

@ -99,26 +99,50 @@ class Form {
$sPropName,
$sValue
);
}
$oMorpho->elements()->reset();
foreach($oMorpho->elements() as $oElement) {
$aValidation = $oElement->optionArray("validation");
if(!empty($aValidation)) {
foreach($aValidation as $sValidation) {
$sMethod = "validate" . ucfirst(strtolower($sValidation));
if(!method_exists($this, $sMethod)) {
throw new \Exception("\Formal\Form::execute(): no validation method for '" . htmlspecialchars($sValidation) . "'");
}
if(empty($aValidation)) {
continue;
}
$sValue = $oElement->value();
foreach($aValidation as $sValidation) {
# If element is readonly, skip process
if($oElement->option("readonly")) {
continue;
}
$sParam = FALSE;
if(strpos($sValidation, ":") !== FALSE) {
$sValidation = strtok($sValidation, ":");
$sParam = strtok(":");
}
$sMethod = "validate" . ucfirst(strtolower($sValidation));
if(!method_exists($this, $sMethod)) {
throw new \Exception("\Formal\Form::execute(): no validation method for '" . htmlspecialchars($sValidation) . "'");
}
if($sParam === FALSE) {
$mValid = $this->$sMethod($sValue, $oMorpho, $oElement);
} else {
$mValid = $this->$sMethod($sValue, $oMorpho, $oElement, $sParam);
}
if($mValid !== TRUE) {
$this->aErrors[] = array(
"element" => $oElement,
"message" => $mValid,
);
$mValid = $this->$sMethod($sValue, $oElement);
if($mValid !== TRUE) {
$this->aErrors[] = array(
"element" => $oElement,
"message" => $mValid,
);
$oElement->setOption("error", TRUE);
break; # one error per element per submit
}
$oElement->setOption("error", TRUE);
break; # one error per element per submit
}
}
}
@ -153,7 +177,7 @@ class Form {
return $this->bPersisted;
}
public function validateRequired($sValue, $oElement) {
public function validateRequired($sValue, \Formal\Form\Morphology $oMorpho, \Formal\Element $oElement) {
if(trim($sValue) !== "") {
return TRUE;
}
@ -161,7 +185,7 @@ class Form {
return "<strong>" . $oElement->option("label") . "</strong> is required.";
}
public function validateEmail($sValue, $oElement) {
public function validateEmail($sValue, \Formal\Form\Morphology $oMorpho, \Formal\Element $oElement) {
if(\Flake\Util\Tools::validEmail($sValue)) {
return TRUE;
}
@ -169,6 +193,28 @@ class Form {
return "<strong>" . $oElement->option("label") . "</strong> should be an email.";
}
public function validateSameas($sValue, \Formal\Form\Morphology $oMorpho, \Formal\Element $oElement, $sReferencePropName) {
$sReferenceValue = $oMorpho->element($sReferencePropName)->value();
if($sValue === $sReferenceValue) {
return TRUE;
}
return "<strong>" . $oElement->option("label") . "</strong> does not match " . $oMorpho->element($sReferencePropName)->option("label") . ".";
}
public function validateUnique($sValue, \Formal\Form\Morphology $oMorpho, \Formal\Element $oElement) {
$oColl = $this->getModelInstance()->getBaseRequester()->addClauseEquals(
$oElement->option("prop"),
$sValue
)->execute();
if($oColl->count() > 0) {
return "<strong>" . $oElement->option("label") . "</strong> has to be unique. Given value is not available.";
}
return TRUE;
}
public function postValue($sPropName) {
return \Flake\Util\Tools::POST($sPropName);
}

View file

@ -15,8 +15,11 @@ class Morphology {
}
public function element($sPropName) {
$this->oElements->reset();
foreach($this->oElements as $oElement) {
$aKeys = $this->oElements->keys();
reset($aKeys);
foreach($aKeys as $sKey) {
$oElement = $this->oElements->getForKey($sKey);
if($oElement->option("prop") === $sPropName) {
return $oElement;
}

View file

@ -1,5 +1,4 @@
<?php
/***************************************************************
* Copyright notice
*
@ -23,13 +22,7 @@
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
define("BAIKAL_CONTEXT", TRUE);
# Bootstraping Baikal
require_once(dirname(dirname(__FILE__)) . "/Frameworks/Baikal/Core/Bootstrap.php");
***************************************************************/
?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">

View file

@ -8,6 +8,9 @@
# Timezone of your users, if unsure, check http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
define("BAIKAL_TIMEZONE", "Europe/Paris");
# Absolute Baïkal URI; end with slash; includes protocol (http:// or https://), port (optional) and subfolders if any
define("BAIKAL_URI", "http://baikal.jeromeschneider.fr/");
##############################################################################
# In this section: Optional configuration: you *may* customize these settings
#
@ -27,6 +30,5 @@ define("BAIKAL_STANDALONE_ALLOWED", TRUE);
# Standalone Server, port number; default 8888
define("BAIKAL_STANDALONE_PORT", 8888);
# Baïkal Web interface admin password hash; Set by Core/Scripts/adminpassword.php
define("BAIKAL_ADMIN_PASSWORDHASH", "5746d6eb0ff2968c494e5d904b8ef4b6");