function pie_response_content() { $serve_fbml = Pie_Request::accepts('text/fbml'); if ($serve_fbml) { // add more fbjs files here } else { // the js files for your app Pie_Response::addScript('plugins/pie/js/Pie.js'); Pie_Response::addScript("http://cdn.jquerytools.org/1.2.3/jquery.tools.min.js"); Pie_Response::addScript('plugins/users/js/Users.js'); // See views/layout/html.php for a facebook script at the top of the <body> } Pie_Response::addStylesheet('plugins/pie/css/Ui.css'); $app = Pie_Config::expect('pie', 'app'); $url = Pie_Request::url(); $module = Pie_Dispatcher::uri()->module; if (empty($module)) { return Pie::event("{$app}/notFound/response/content"); } $action = Pie_Dispatcher::uri()->action; $event = "{$module}/{$action}/response/content"; if (!Pie::canHandle($event)) { return Pie::event("{$app}/notFound/response/content"); } // Go ahead and fire the event, returning the result. return Pie::event($event); }
/** * Ticker that scrolls its contents with various speeds and pauses * * @param $fields * An associative array of fields, possibly including: * * "content_fbml" => string * The FBML content of the ticker. The first top-level element * should contain sub-elements, and their sizes determine where * the ticker would pause between automatically scrolling. * The ticker animates by scrolling its inner contents. * * "vertical" => bool * Defaults to true. If false, the ticker scrolls horizontally. * * "speed" => bool * The scrolling speed. * This is the number of items that would scroll by in 1 second, * if there were no pauses. * When the speed is positive, vertical tickers scroll down, and * horizontal tickers scroll to the right. New content seems to come in * from the bottom (for vertical tickers) or right (for horizontal tickers) * as the ticker scrolls. The element inside the ticker will start out * aligned with the top side of the ticker (for vertical tickers), * or the left side of the ticker (for horizontal tickers). * When the speed is negative, all this faces the other way. * * "pause_ms" => int * Defaults to 2000. This is the number of milliseconds to wait * after each second-level element of $content_fbml is automatically * scrolled completely into view. * * "pause_ms_min" => int * If set, then the number of milliseconds to pause is a random * integer between $pause_ms_min and $pause_ms. * * "scrollbars" => bool * Defaults to true. If true, shows scrollbars, otherwise doesn't. * (Note: this will let the user know how much content is left, * and be able to see it before it would automatically scroll into view.) * * "scrollbars_pause_ms" => int * Defaults to 500. The ticker pauses its automatic scrolling when the user * starts using the scrollbars. This is the number of milliseconds to wait * until resuming the automatic scrolling. * * "anim_ms" => int * Defaults to 100. This is the number of milliseconds between calls to * autoScroll. * * "initial_scroll_mode" => int * Defaults to 'auto'. This is the mode that scrolling starts out in. * Possible values are 'auto' and 'paused'. * * "ease" => string * Optional. If set, specifies the name of the ease function */ function pie_tool_ticker($fields = array()) { $defaults = array('vertical' => true, 'speed' => 1, 'pause_ms' => 2000, 'scrollbars' => true, 'scrollbars_pause_ms' => 500, 'anim_ms' => 100); $fields2 = array_merge($defaults, $fields); if (!isset($fields2['pause_ms_min'])) { $fields2['pause_ms_min'] = $fields2['pause_ms']; } if (!isset($fields2['content_fbml'])) { $li_array = array(); for ($i = 0; $i < 1000; ++$i) { $li_array[] = "<li>Missing \$content_fbml parameter. This is just example {$i}...</li>"; } $default_content = implode("\n", $li_array); if ($fields2['vertical']) { $fields2['content_fbml'] = "<ul class='error'>{$default_content}</ul>"; } else { $fields2['content_fbml'] = "<ul class='error'>{$default_content}</ul>"; } } // TODO: develop one for just HTML, // and then check for FBML environment, instead of assuming it. Pie_Response::addScript('plugins/pie/fbjs/Pie.fb.js'); Pie_Response::addScript('plugins/pie/fbjs/Ticker.fb.js'); Pie_Response::addStylesheet('plugins/pie/css/Ticker.css'); $direction_class = $fields2['vertical'] ? 'vertical' : 'horizontal'; $scrollbars_class = $fields2['scrollbars'] ? 'scrollbars' : ''; return Pie_Html::tag('div', array('id' => 'ticker', 'class' => "ticker {$direction_class} {$scrollbars_class}"), $fields2['content_fbml']); }
function users_after_pie_reroute($params, &$stop_dispatch) { $uri = Pie_Dispatcher::uri(); $app = Pie_Config::expect('pie', 'app'); $ma = $uri->module . '/' . $uri->action; $requireComplete = Pie_Config::get('users', 'requireComplete', array()); if (isset($requireComplete[$ma])) { $redirect_action = is_string($requireComplete[$ma]) ? $requireComplete[$ma] : "{$app}/login"; $test_complete = true; } else { $requireLogin = Pie_Config::get('users', 'requireLogin', array()); if (!isset($requireLogin[$ma])) { // We don't have to require complete or login here return; } $redirect_action = is_string($requireLogin[$ma]) ? $requireLogin[$ma] : "{$app}/login"; } // First, try to get the user $user = Users::loggedInUser(); if (!$user) { // Try authenticating with facebook $module = Pie_Dispatcher::uri()->module; $app_id = Pie_Config::expect('users', 'facebookApps', $module, 'appId'); $user = Users::authenticate('facebook', $app_id); } if (!$user) { $uri->onSuccess = $uri->module . '/' . $uri->action; $uri->onCancel = "{$app}/welcome"; if ($uri->onSuccess === $redirect_action) { // avoid a redirect loop $uri->onSuccess = "{$app}/home"; } $parts = explode('/', $redirect_action); $uri->action = $parts[0]; $uri->action = $parts[1]; } // If have requireLogin but not requireComplete, then // simply change the underlying URI without redirecting if (empty($test_complete)) { return; } // If we are here, we should check if the user account is complete $complete = Pie::event('users/account/complete'); if ($complete) { // good, nothing else to complete return; } // redirect to account page $account_action = Pie_Config::expect('users', 'accountAction', $uri->module); if ($ma != $account_action) { // Make the user launch into setting up their account. // If they want to return to this URL later, they can do it on their own. Pie_Response::redirect($account_action); $stop_dispatch = true; return; } }
/** * This is a tool for selecting photos (to possibly add) * @param $facebook * Optional. You can provide instance of the Facebook class. * @param $upload * Defaults to false. If true, shows an option to upload, as well. * @param $action_uri * Defaults to 'items/addPhoto'. The URI to submit the form to. * @param $filter_visible * Optional string. Set to 'everyone' to only display albums visible to everyone. * @param $on_success * Optional string. The url to redirect to after a photo is added or uploaded. */ function items_addPhoto_tool($params) { if (isset(Users::$facebook)) { $facebook = Users::$facebook; } else { $app = Pie_Config::expect('pie', 'app'); if (!isset(Users::$facebooks[$app])) { throw new Pie_Exception_MissingObject(array('name' => 'Users::$facebooks[' . $app . ']')); } $facebook = Users::$facebooks[$app]; } $defaults = array('facebook' => $facebook, 'upload' => false, 'action_uri' => 'items/addPhoto', 'on_success' => Pie_Request::url()); extract(array_merge($defaults, $params)); if (!$facebook instanceof Facebook) { throw new Pie_Exception_WrongType(array('field' => '$facebook', 'type' => 'Facebook')); } if (isset($_REQUEST['_pie']['onSuccess'])) { $on_success = $_REQUEST['_pie']['onSuccess']; } $sn = Pie_Session::name(); $sid = Pie_Session::id(); $photos = array(); if (isset($aid)) { $photos = Items::facebookPhotos($facebook, $aid); return Pie::view('items/tool/addPhotoList.php', compact('photos')); } $facebook->require_login(); $album_rows = Items::facebookAlbums($facebook); $albums = array(); foreach ($album_rows as $ar) { if (isset($filter_visible) and $ar['visible'] != $filter_visible) { continue; } $albums[$ar['aid']] = $ar['name']; } $albums = $albums; if (count($album_rows)) { $row = reset($album_rows); $photos = Items::facebookPhotos($facebook, $row['aid']); } $throbber_url = Pie_Html::themedUrl('plugins/items/img/anim/throbber.gif'); $url_json = json_encode(Pie_Uri::url($action_uri)); Pie_Response::addStylesheet('plugins/items/css/Items.css'); if (Pie_Request::accepts('text/fbml')) { Pie_Response::addScript('plugins/items/fbjs/Items.fb.js'); } else { Pie_Response::addScript('plugins/items/js/Items.js'); } if (is_bool($upload)) { $upload = uniqid('up.', false); } $addPhoto_url_json = json_encode(Pie_Uri::url('items/addPhoto')); Pie_Response::addScriptLine("\tPie.Items.urls['items/addPhoto'] = {$addPhoto_url_json};"); return Pie::view('items/tool/addPhoto.php', compact('action_uri', 'on_success', 'on_added', 'albums', 'photos', 'throbber_url', 'upload')); }
function users_after_pie_addScriptLines() { $app = Pie_Config::expect('pie', 'app'); $app_json = json_encode($app); $fb_app_info = Pie_Config::get('users', 'facebookApps', $app, array()); if ($fb_app_info) { unset($fb_app_info['secret']); $fb_app_info_json = json_encode($fb_app_info); Pie_Response::addScriptLine("// users {{ \n" . "\t\tif (!Pie) Pie = {}; if (!Pie.Users) Pie.Users = {};\n" . "\t\tif (!Pie.Users.facebookApps) Pie.Users.facebookApps = {};\n" . "\t\tPie.Users.facebookApps[{$app_json}] = {$fb_app_info_json}\n" . "// }} users \n"); } }
function pie_response_notices() { $errors = Pie_Response::getErrors(); if (empty($errors)) { return ''; } $result = "<ul class='pie_errors'>"; foreach ($errors as $e) { $result .= "<li>" . $e->getMessage() . "</li>"; } return $result .= "</ul>"; }
function users_contact_tool($params) { $defaults = array('uri' => 'users/contact', 'omit' => array(), 'fields' => array(), 'title' => "Contact Info", 'collapsed' => false, 'toggle' => false, 'editing' => true, 'complete' => true, 'inProcess' => false, 'prompt' => "In order for things to work, we must be able to reach you.", 'button_content' => 'OK'); extract(array_merge($defaults, $params)); $default_fields = array('first_name' => array('type' => 'text', 'label' => 'First Name'), 'last_name' => array('type' => 'text', 'label' => 'Last Name'), 'email_address' => array('type' => 'text', 'label' => 'Email')); $fields = array_merge($default_fields, $fields); $user = Users::loggedInUser(); if (!$user) { throw new Users_Exception_NotLoggedIn(); } $email = null; $missing_fields = Users::accountStatus($email); if (isset($user->first_name)) { $fields['first_name']['value'] = $user->first_name; } if (isset($user->last_name)) { $fields['last_name']['value'] = $user->last_name; } if (isset($user->email_address)) { $fields['email_address']['value'] = $user->email_address; } else { if ($email) { $link = Pie_Html::a('#resend', array('class' => 'users_contact_tool_resend'), "You can re-send the activation email"); switch ($email->state) { case 'active': if ($email->user_id == $user->id) { $message = "Please confirm this email address.<br>{$link}"; } else { $message = "This email seems to belong to another user"; } break; case 'suspended': $message = "This address has been suspended."; break; case 'unsubscribed': $message = "The owner of this address has unsubscribed"; break; case 'unverified': default: $message = "Not verified yet.<br>{$link}"; break; } $fields['email_address']['value'] = $email->address; $fields['email_address']['message'] = $message; } } $on_success = isset($_REQUEST['_pie']['onSuccess']) ? $_REQUEST['_pie']['onSuccess'] : Pie_Request::url(); Pie_Response::addScript('plugins/users/js/Users.js'); $form = $static = compact('fields'); return Pie::tool('pie/panel', compact('uri', 'on_success', 'form', 'static', 'title', 'collapsed', 'toggle', 'complete', 'editing', 'inProcess', '_form_static')); }
function users_activate_post() { $email_address = Pie_Dispatcher::uri()->email_address; $mobile_number = Pie_Dispatcher::uri()->mobile_number; $email = null; $mobile = null; if ($email_address) { $email = new Users_Email(); $email->address = $email_address; // NOTE: not sharded by user_id if (!$email->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'email', 'criteria' => "address = {$email_address}")); } $user = new Users_User(); $user->id = $email->user_id; if (!$user->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id)); } if ($email->activation_code != $_REQUEST['code']) { throw new Pie_Exception("The activation code does not match.", 'code'); } $user->setEmailAddress($email->address); // may throw exception $type = "email address"; } if ($mobile_number) { $mobile = new Users_Mobile(); $mobile->number = $mobile_number; // NOTE: not sharded by user_id if (!$mobile->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'mobile phone', 'criteria' => "number = {$mobile_number}")); } $user = new Users_User(); $user->id = $mobile->user_id; if (!$user->retrieve()) { throw new Pie_Exception_MissingRow(array('table' => 'user', 'criteria' => 'id = ' . $user->id)); } if ($mobile->activation_code != $_REQUEST['code']) { throw new Pie_Exception("The activation code does not match.", 'code'); } $user->setMobileNumber($mobile->number); // may throw exception $type = "mobile number"; } if ($type) { Pie_Response::addNotice("users/activate", "Your {$type} has been activated."); } Users::$cache['user'] = $user; }
/** * This tool is meant to be wrapped in a <form> tag * @param array $params * An associative array of parameters, containing: * "fields" => an associative array of fieldname => fieldinfo pairs, * where fieldinfo contains the following: * "type" => the type of the field (@see Pie_Html::smartTag()) * "attributes" => additional attributes for the field input * "value" => the initial value of the field input * "options" => options for the field input (if type is "select", "checkboxes" or "radios") * "message" => initial message, if any to put in the field's message space */ function pie_form_tool($params) { if (empty($params['fields'])) { return ''; } $field_defaults = array('type' => 'text', 'attributes' => array(), 'value' => null, 'options' => array(), 'message' => ''); $tr_array = array(); foreach ($params['fields'] as $name => $field) { if (!is_array($field)) { $name2 = '"' . addslashes($name) . '"'; throw new Pie_Exception_WrongType(array('field' => "\$params[{$name2}]", 'type' => 'array')); } $field2 = array_merge($field_defaults, $field); $type = $field2['type']; $attributes = $field2['attributes']; $value = $field2['value']; $options = $field2['options']; $message = $field2['message']; $attributes['name'] = $name; if (ctype_alnum($type)) { if (isset($attributes['class'])) { if (is_array($attributes['class'])) { foreach ($attributes['class'] as $k => $v) { $attributes['class'][$k] .= " {$type}"; } } else { $attributes['class'] .= " {$type}"; } } else { $attributes['class'] = " {$type}"; } } switch ($type) { case 'textarea': $tr_rest = "<td class='pie_form_fieldinput' colspan='2'>" . Pie_Html::smartTag($type, $attributes, $value, $options) . "</td></tr><tr><td class='pie_form_placeholder'>" . "</td><td class='pie_form_undermessage pie_form_textarea_undermessage' colspan='2'>" . "<div class='pie_form_undermessagebubble'>{$message}</div></td>"; break; default: $tr_rest = "<td class='pie_form_fieldinput'>" . Pie_Html::smartTag($type, $attributes, $value, $options) . "</td><td class='pie_form_fieldmessage pie_form_{$type}_message'>{$message}</td>" . "</tr><tr><td class='pie_form_placeholder'>" . "</td><td class='pie_form_undermessage pie_form_{$type}_undermessage' colspan='2'>" . "<div class='pie_form_undermessagebubble'></div></td>"; break; } $label = isset($field['label']) ? $field['label'] : $name; $name_text = Pie_Html::text($name); $tr_array[] = "<tr><td class='pie_form_fieldname' data-fieldname=\"{$name_text}\">{$label}</td>{$tr_rest}</tr>"; } $result = "<table class='pie_form_tool_table' cellspacing='0'>\n" . implode("\n\t", $tr_array) . "\n</table>"; Pie_Response::addScript('plugins/pie/js/PieTools.js'); return $result; }
/** * The default implementation. */ function pie_errors($params) { extract($params); /** * @var Exception $exception */ if (!empty($exception)) { Pie_Response::addError($exception); $errors = Pie_Response::getErrors(); } $errors_array = Pie_Exception::toArray($errors); $exception_array = Pie_Exception::toArray($exception); // Simply return the errors, if this was an AJAX request if ($is_ajax = Pie_Request::isAjax()) { switch (strtolower($is_ajax)) { case 'json': default: $json = json_encode(array('errors' => $errors_array, 'exception' => $exception_array)); $callback = Pie_Request::callback(); echo $callback ? "{$callback}({$json})" : $json; } return; } // Forward internally, if it was requested if (isset($_REQUEST['_pie']['onErrors'])) { $uri = Pie_Dispatcher::uri(); $uri2 = Pie_Uri::from($_REQUEST['_pie']['onErrors']); if ($uri !== $uri2) { Pie_Dispatcher::forward($uri2); return; // we don't really need this, but it's here anyway } } if (Pie::eventStack('pie/response')) { // Errors happened while rendering response. Just render errors view. return Pie::view('pie/errors.php', $params); } try { // Try rendering the response, expecting it to // display the errors along with the rest. $ob = new Pie_OutputBuffer(); Pie::event('pie/response', compact('errors', 'exception', 'errors_array', 'exception_array')); $ob->endFlush(); } catch (Exception $exception) { $output = $ob->getClean(); return Pie::event('pie/exception', compact('exception')); } }
function users_before_pie_response_notices() { if ($user = Users::loggedInUser()) { if (empty($user->email_address)) { $email = new Users_Email(); $email->user_id = $user->id; if ($email->retrieve()) { $resend_button = "<button id='notices_set_email'>try again</button>"; Pie_Response::addNotice('email', "Please check your email to activate your account. Any problems, {$resend_button}"); } else { $set_email_button = "<button id='notices_set_email'>set an email address</button> for your account."; Pie_Response::addNotice('email', "You need to {$set_email_button}"); } Pie_Response::addScriptLine("jQuery(function() {\n\t\t\t\t\$('#notices_set_email').click(function() { Pie.Users.setEmail(); });\n\t\t\t}); "); } } }
function users_account_tool($params) { $defaults = array('uri' => 'users/account', 'omit' => array(), 'fields' => array(), 'title' => "Basic Info", 'editing' => true, 'complete' => true, 'inProcess' => false, 'collapsed' => false, 'toggle' => false); extract(array_merge($defaults, $params)); $default_fields = array('username' => array('type' => 'text', 'label' => 'Choose Username'), 'gender' => array('type' => 'select', 'label' => 'I am', 'options' => array('male' => 'a man', 'female' => 'a woman')), 'orientation' => array('type' => 'select', 'label' => 'Orientation', 'options' => array('straight' => 'straight', 'gay' => 'gay', 'bi' => 'bi')), 'relationship_status' => array('type' => 'select', 'label' => 'Status', 'options' => array('single' => "I'm single", 'open' => "I'm in an open relationship", 'relationship' => "I'm in a relationship", 'engaged' => "I'm engaged", 'married' => "I'm married", 'complicated' => "It's complicated", 'widowed' => "I'm widowed")), 'birthday' => array('type' => 'date', 'label' => 'My Birthday', 'options' => array('year_from' => '1920', 'year_to' => date('Y') - 16)), 'zipcode' => array('type' => 'text', 'label' => 'Zipcode', 'attributes' => array('maxlength' => 5))); $fields = array_merge($default_fields, $fields); $user = Users::loggedInUser(); if (!$user) { throw new Users_Exception_NotLoggedIn(); } if (isset($user->gender)) { $fields['gender']['value'] = $user->gender; } if (isset($user->desired_gender)) { if ($user->desired_gender == 'either') { $fields['orientation']['value'] = 'bi'; } else { if (isset($user->gender)) { $fields['orientation']['value'] = $user->gender != $user->desired_gender ? 'straight' : 'gay'; } } } if (isset($user->relationship_status)) { $fields['relationship_status']['value'] = $user->relationship_status; } if (isset($user->birthday)) { $fields['birthday']['value'] = date("Y-m-d", Users::db()->fromDate($user->birthday)); } if (isset($user->zipcode)) { $fields['zipcode']['value'] = $user->zipcode; } if (isset($user->username)) { $fields['username']['value'] = $user->username; } foreach ($omit as $v) { unset($fields[$v]); } $on_success = isset($_REQUEST['_pie']['onSuccess']) ? $_REQUEST['_pie']['onSuccess'] : Pie_Request::url(); Pie_Response::addScript('plugins/users/js/Users.js'); $form = $static = compact('fields'); return Pie::tool('pie/panel', compact('uri', 'title', 'form', 'static', 'on_success', 'complete', 'collapsed', 'toggle', 'editing', 'inProcess', '_form_static')); }
function pie_addScriptLines() { $app = Pie_Config::expect('pie', 'app'); $uri = Pie_Dispatcher::uri(); $proxies_json = json_encode(Pie_Config::get('pie', 'proxies', array())); $uri_json = json_encode($uri->toArray()); $url = Pie_Request::url(); $url_json = json_encode($url); $proxy_url_json = json_encode(Pie_Uri::url($url)); $base_url = json_encode(Pie_Request::baseUrl()); Pie_Response::addScriptLine(<<<EOT // pie {{ \t\tPie.info = { \t\t\t"proxies": {$proxies_json}, \t\t\t"uri": {$uri_json}, \t\t\t"url": {$url_json}, \t\t\t"proxyUrl": {$proxy_url_json}, \t\t\t"baseUrl": {$base_url} \t\t}; EOT ); $uris = Pie_Config::get('pie', 'javascript', 'uris', array()); $urls = array(); foreach ($uris as $u) { $urls["{$u}"] = Pie_Uri::url("{$u}"); } $urls_json = json_encode($urls); Pie_Response::addScriptLine("\t\tPie.urls = {$urls_json};"); // Export more variables to inline js $app = Pie_Config::expect('pie', 'app'); $app_json = json_encode($app); Pie_Response::addScriptLine("\t\tPie.app = {$app_json};\n" . "// }} pie"); $snf = Pie_Config::get('pie', 'session', 'nonceField', 'nonce'); $nonce = isset($_SESSION[$snf]) ? $_SESSION[$snf] : null; if ($nonce) { $nonce_json = json_encode($nonce); Pie_Response::addScriptLine("\t\tPie.nonce = {$nonce_json};"); } }
function users_account_validate() { $birthday_year = $birthday_month = $birthday_day = null; extract($_REQUEST); /* $field_names = array( 'first_name' => 'First name', 'last_name' => 'Last name', 'username' => 'Username', 'gender' => 'Your gender', 'desired_gender' => 'Gender preference', 'orientation' => 'Orientation', 'relationship_status' => 'Status', 'zipcode' => 'Zipcode' ); foreach ($field_names as $name => $label) { if (isset($_POST[$name]) and !($_POST[$name])) { Pie_Response::addError( new Pie_Exception_RequiredField(array('field' => $label), $name) ); } }; */ if (isset($birthday_year)) { if (!checkdate($birthday_month, $birthday_day, $birthday_year)) { $field = 'Birthday'; $range = 'a valid date'; Pie_Response::addError(new Pie_Exception_WrongValue(compact('field', 'range'), 'birthday')); } } if (isset($username)) { try { Pie::event('users/validate/username', compact('username')); } catch (Exception $e) { Pie_Response::addError($e); } } }
/** * Gets or sets whether the response is buffered. * @param boolean $new_value * Optional. If not present, just returns the current value of this setting. * If true or false, sets the setting to this value, and returns the setting's old value. * @return boolean */ static function isBuffered($new_value = null) { $old_value = self::$isBuffered; if (isset($new_value)) { self::$isBuffered = $new_value; } return $old_value; }
/** * Default pie/response handler. * 1. Gets some slots, depending on what was requested. * 2. Renders them in a layout * The layout expects "title", "dashboard" and "contents" slots to be filled. */ function pie_response($params) { extract($params); /** * @var Exception $exception * @var array $errors */ // Redirect to success page, if requested. $is_ajax = Pie_Request::isAjax(); if (empty($errors) and empty($exception)) { if (!$is_ajax and isset($_REQUEST['_pie']['onSuccess'])) { $on_success = $_REQUEST['_pie']['onSuccess']; if (Pie_Config::get('pie', 'response', 'onSuccessShowFrom', true)) { $on_success = Pie_Uri::url($on_success . '?_pie[fromSuccess]=' . Pie_Dispatcher::uri()); } Pie_Response::redirect($on_success); return; } } // Get the requested module $uri = Pie_Dispatcher::uri(); if (!isset($module)) { $module = $uri->module; if (!isset($module)) { $module = 'pie'; Pie_Dispatcher::uri()->module = 'pie'; } } // Get the main module (the app) $app = Pie_Config::expect('pie', 'app'); // Add some javascript to inform the front end of important URLs Pie::event('pie/addScriptLines'); // What to do if this is an AJAX request if ($is_ajax) { $slot_names = Pie_Request::slotNames(); if (!isset($slot_names)) { $slot_names = Pie_Config::get($module, 'response', 'slotNames', array('content' => null, 'dashboard' => null, 'title' => null, 'notices' => null)); } $slots = array(); $stylesheets = array(); $stylesInline = array(); $scripts = array(); $scriptLines = array(); if (is_array($slot_names)) { foreach ($slot_names as $slot_name => $v) { $slots[$slot_name] = Pie_Response::fillSlot($slot_name, 'default'); $stylesheets[$slot_name] = Pie_Response::stylesheetsArray($slot_name); $stylesInline[$slot_name] = Pie_Response::stylesInline($slot_name); $scripts[$slot_name] = Pie_Response::scriptsArray($slot_name); $scriptLines[$slot_name] = Pie_Response::scriptLines($slot_name); } } $timestamp = microtime(true); $echo = Pie_Request::contentToEcho(); // Render a JSON layout for ajax $to_encode = compact('slots', 'stylesheets', 'stylesInline', 'scripts', 'scriptLines', 'timestamp', 'echo'); // Cut down on the response size foreach (array('slots', 'stylesheets', 'stylesInline', 'scripts', 'scriptLines') as $f) { $is_empty = true; if (is_array($to_encode[$f])) { foreach ($to_encode[$f] as $k => $v) { if (isset($v)) { $is_empty = false; } else { unset($to_encode[$f][$k]); } } } else { if (!empty($to_encode[$f])) { $is_empty = false; } } if ($is_empty) { unset($to_encode[$f]); } } switch (strtolower($is_ajax)) { case 'json': default: $json = json_encode($to_encode); $callback = Pie_Request::callback(); echo $callback ? "{$callback}({$json})" : $json; } return; } // If this is a request for a regular webpage, // fill the usual slots and render a layout. // Attach stylesheets and scripts if (Pie_Request::accepts('text/fbml')) { Pie_Response::addStylesheet("css/fbml.css"); Pie_Response::addScript('plugins/pie/fbjs/Pie.fb.js'); } else { Pie_Response::addStylesheet("css/html.css"); Pie_Response::addScript('plugins/pie/js/Pie.js'); } // Get all the usual slots for a webpage $slot_names = Pie_Config::get($module, 'response', 'slotNames', array('content' => null, 'dashboard' => null, 'title' => null, 'notices' => null)); $slots = array(); foreach ($slot_names as $sn => $v) { $slots[$sn] = Pie_Response::fillSlot($sn, 'default'); } $output = Pie_Response::output(); if (isset($output)) { if ($output === true) { return; } if (is_string($output)) { echo $output; } return; } if (Pie_Request::accepts('text/fbml')) { // Render a full FBML layout $layout_view = Pie_Config::get($app, 'response', 'layout_fbml', "{$app}/layout/fbml.php"); echo Pie::view($layout_view, $slots); } else { // Render a full HTML layout $layout_view = Pie_Config::get($app, 'response', 'layout_html', "{$app}/layout/html.php"); echo Pie::view($layout_view, $slots); } }
<?php echo json_encode(compact(Pie_Response::getRequestedSlots()));
echo $dashboard; ?> </div> <?php if ($notices) { ?> <div id="notices_slot"> <?php echo $notices; ?> </div> <?php } ?> <div id="content_slot"> <?php echo $content; ?> </div> <br style="clear: both;"> </div> <?php echo Pie_Html::script(Pie_Response::scriptLines()); echo Pie_html::script("Pie.ready();"); ?> </fb:fbml>
/** * This tool generates a panel with a <form> tag inside it * @param array $params * An associative array of parameters, containing: * "uri" => the uri or url the form should post to * "title" => the title of the panel * "complete" => boolean, indicating whether the data on the server is in a complete state * "editing" => boolean, indicating whether to show the form in the "editing" state * "form" => string containing the contents of the form portion of the panel * which is normally generated by a "pie/form" tool * "static" => string containing the contents of the "static" portion * "collapsed" => defaults to false. Whether the panel is shown as collapsed into just the header * "toggle" => defaults to false. The events that cause toggling of collapsed state. * If the string is 'click' then toggles the panel on clicks. * If the string is 'move' then toggles the panel on mouseenter/mouseleave. * "edit_button" => optional, to override the edit button * "save_button" => optional, to override the save button * "cancel_button" => optional, to override the cancel button * "panel_classes" => optional, additional classes for the panel * "snf" => optional. The name of the nonce field in the session * "on_success" => optional. The URI to redirect to on success * "on_errors" => optional. The URI to display if errors occur * "inProcess" => optional. Causes the panel to appear as if it's a step in a process. */ function pie_panel_tool($params) { foreach (array('title', 'complete', 'editing', 'static', 'form') as $f) { if (!array_key_exists($f, $params)) { throw new Pie_Exception_RequiredField(array('field' => '$' . $f)); } } $defaults = array('edit_button' => "<button type='submit' class='basic16 basic16_edit pie_panel_tool_edit'>edit</button>", 'save_button' => "<button type='submit' class='basic16 basic16_check pie_panel_tool_save'>save</button>", 'cancel_button' => "<button type='reset' class='basic16 basic16_cancel pie_panel_tool_cancel'>cancel</button>", 'panel_classes' => '', 'uri' => null, 'collapsed' => false, 'toggle' => false, 'inProcess' => false, 'on_success' => null, 'on_errors' => null, 'snf' => null); extract(array_merge($defaults, $params)); $more_class = $params['complete'] ? 'pie_panel_tool_complete' : 'pie_panel_tool_incomplete'; $panel_classes = "{$more_class} {$panel_classes}"; $title_div = "<div class='pie_panel_tool_title'>{$title}</div>"; if ($uri) { $header = "<div class='pie_panel_tool_buttons'>{$save_button}{$cancel_button}{$edit_button}</div>{$title_div}"; } else { $header = $title_div; } // Whether to display the panel one way or the other if ($inProcess) { $header = $title_div; if (is_array($form)) { $form['fields']['_pie_buttons'] = array('type' => 'buttons', 'label' => '', 'options' => array('continue' => 'Continue'), 'attributes' => array('class' => 'basic32 basic32_right', 'type' => 'submit')); } else { $form .= "<div class='pie_panel_tool_formbuttons'><button type='submit' class='pie_panel_tool_continue basic32 basic32_right' value='continue'>Continue</button></div>"; } } // Turn the static into a string, if it's an array // This currently doesn't work well, because it causes // a bug where the outer form is submitted twice. if (is_array($static)) { foreach ($static['fields'] as $k => $f) { if (Pie::ifset($static['fields'][$k]['type'])) { switch ($static['fields'][$k]['type']) { case 'textarea': $static['fields'][$k]['value'] = str_replace("\n", "<br>", $static['fields'][$k]['value']); break; case 'date': if (!isset($static['fields'][$k]['options']['date'])) { $static['fields'][$k]['options']['date'] = "M j, Y"; } break; case 'buttons': unset($static['fields'][$k]); } } $static['fields'][$k]['type'] = 'static'; } $static = Pie::tool('pie/form', $static, array('id' => 'static')); } // Turn the form into a form if (is_array($form)) { $form = Pie::tool('pie/form', $form); } // Build the panel $panel = "<div class='pie_panel_tool_header'>{$header}</div>" . "<div class='pie_panel_tool_form'>{$form}</div>"; if (isset($snf) or isset($on_success) or isset($on_errors)) { $panel .= "<div>" . Pie_Html::formInfo($on_success, $on_errors, $snf) . "</div>"; } if ($uri) { $panel = Pie_Html::form($uri, 'post', array('class' => "pie_panel_tool_panel"), $panel); } $panel .= "<div class='pie_panel_tool_static'>{$static}</div>"; if ($editing) { $panel_classes .= ' pie_editing'; } if ($complete) { $panel_classes .= ' pie_complete'; } if ($collapsed) { $panel_classes .= ' pie_collapsed'; } if ($toggle === 'click') { $panel_classes .= ' pie_panel_tool_toggle_onclick'; } if ($toggle === 'move') { $panel_classes .= ' pie_panel_tool_toggle_move'; } Pie_Response::addScript('plugins/pie/js/PieTools.js'); Pie_Response::addStylesheet('plugins/pie/css/Ui.css'); if (isset($_form_static)) { Pie_Response::setSlot('form', $form); Pie_Response::setSlot('static', $static); } return "<div class='pie_panel_tool_container {$panel_classes}'>{$panel}</div>"; }
function pie_tool_zoomer($fields) { Pie_Response::addScript('plugins/pie/js/PieTools.js'); Pie_Response::addStylesheet('plugins/pie/css/Pie.css'); return Pie::view('pie/tool/zoomer.php'); }
/** * Dispatches a URI for internal processing. * Usually called by a front controller. * @param mixed $uri * Optional. You can pass a custom URI to dispatch. Otherwise, PIE will attempt * to route the requested URL, if any. * @param array $check * Optional. Pass array() to skip checking whether the URI can be obtained * as a result of routing some URL. * @return boolean */ static function dispatch($uri = null, $check = array('accessible')) { if (!is_array($check)) { $check = array('accessible'); } if (isset($uri)) { if (in_array('accessible', $check)) { if (!Pie_Uri::url($uri)) { // We shouldn't dispatch to this URI $uri = Pie_Uri::from(array()); } } self::$uri = Pie_Uri::from($uri); } else { self::$uri = Pie_Request::uri(); } // if file or dir is requested, try to serve it $served = false; $skip = Pie_Config::get('pie', 'dispatcherSkipFilename', false); $filename = $skip ? false : Pie_Request::filename(); if ($filename) { if (is_dir($filename)) { $served = Pie::event("pie/dir", compact('filename', 'routed_uri')); $dir_was_served = true; } else { $served = Pie::event("pie/file", compact('filename', 'routed_uri')); $dir_was_served = false; } } // if response was served, then return if ($served) { self::result($dir_was_served ? "Dir served" : "File served"); return true; } // This loop is for forwarding $max_forwards = Pie_Config::get('pie', 'maxForwards', 10); for ($try = 0; $try < $max_forwards; ++$try) { // Make an array from the routed URI $routed_uri_array = array(); if (self::$uri instanceof Pie_Uri) { $routed_uri_array = self::$uri->toArray(); } // If no module was found, then respond with noModule and return if (!isset(self::$uri->module)) { Pie::event("pie/noModule", $routed_uri_array); // should echo things self::result("No module"); return false; } $module = self::$uri->module; // Implement restricting of modules we are allowed to access $routed_modules = Pie_Config::get('pie', 'routedModules', null); if (isset($routed_modules)) { if (!in_array($module, $routed_modules)) { Pie::event('pie/notFound', $routed_uri_array); // should echo things self::result("Unknown module"); return false; } } else { if (!Pie::realPath("handlers/{$module}")) { Pie::event('pie/notFound', $routed_uri_array); // should echo things self::result("Unknown module"); return false; } } try { // Fire a pure event, for aggregation etc if (!in_array('pie/prepare', self::$skip)) { Pie::event('pie/prepare', $routed_uri_array, true); } // Perform validation if (!in_array('pie/validate', self::$skip)) { Pie::event('pie/validate', $routed_uri_array); // Check if any errors accumulated if (Pie_Response::getErrors()) { // There were validation errors -- render a response self::errors(null, $module, null); self::result('Validation errors'); return false; } } // Time to instantiate some app objects from the request if (!in_array('pie/objects', self::$skip)) { Pie::event('pie/objects', $routed_uri_array, true); } // We might want to reroute the request if (!in_array('pie/reroute', self::$skip)) { $stop_dispatch = Pie::event('pie/reroute', $routed_uri_array, true); if ($stop_dispatch) { self::result("Stopped dispatch"); return false; } } if (Pie_Request::isPost()) { if (!in_array('pie/post', self::$skip)) { // Make some changes to server state, possibly Pie::event('pie/post', $routed_uri_array); } } // Time to instantiate some app objects from the request if (!in_array('pie/analytics', self::$skip)) { Pie::event('pie/analytics', $routed_uri_array, true); } // Start buffering the response, unless otherwise requested if ($handler = Pie_Response::isBuffered()) { $ob = new Pie_OutputBuffer($handler); } // Generate and render a response Pie::event("pie/response", $routed_uri_array); if (!empty($ob)) { $ob->endFlush(); } self::result("Served response"); return true; } catch (Pie_Exception_DispatcherForward $e) { // Go again, this time with a different URI. self::$uri = Pie_Uri::from($e->uri); if (is_array($e->skip)) { self::$skip = $e->skip; } else { // Don't process the POST fields this time around self::$skip = array('pie/post'); } // We'll be handling errors anew self::$handling_errors = false; } catch (Pie_Exception_DispatcherErrors $e) { if (!empty($ob)) { $partial_response = $ob->getClean(); } else { $partial_response = null; } self::errors(null, $module, $partial_response); self::result("Rendered errors"); return true; } catch (Exception $exception) { if (!empty($ob)) { $partial_response = $ob->getClean(); } else { $partial_response = null; } self::errors($exception, $module, $partial_response); self::result("Exception occurred"); return false; } } // If we are here, we have done forwarding too much throw new Pie_Exception_Recursion(array('function_name' => 'Dispatcher::forward()')); }