X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=lib%2Faction.php;h=26afd7bfbe0667c085aad99144084f9957a27cf3;hb=1d8b19fe545e62370dc7c1810478021473d5357f;hp=81aa8eb12c2b5bf26510cfa0b10137fac839fbc2;hpb=a10edb3183928d40c0567ea912a2530ebfb17683;p=quix0rs-gnu-social.git diff --git a/lib/action.php b/lib/action.php index 81aa8eb12c..26afd7bfbe 100644 --- a/lib/action.php +++ b/lib/action.php @@ -28,9 +28,7 @@ * @link http://status.net/ */ -if (!defined('STATUSNET') && !defined('LACONICA')) { - exit(1); -} +if (!defined('GNUSOCIAL')) { exit(1); } require_once INSTALLDIR.'/lib/noticeform.php'; require_once INSTALLDIR.'/lib/htmloutputter.php'; @@ -55,7 +53,23 @@ require_once INSTALLDIR.'/lib/htmloutputter.php'; */ class Action extends HTMLOutputter // lawsuit { - var $args; + // This should be protected/private in the future + public $args = array(); + + // Action properties, set per-class + protected $action = false; + protected $ajax = false; + protected $menus = true; + protected $needLogin = false; + protected $needPost = false; + + // The currently scoped profile (normally Profile::current; from $this->auth_user for API) + protected $scoped = null; + + // Related to front-end user representation + protected $format = null; + protected $error = null; + protected $msg = null; /** * Constructor @@ -73,6 +87,44 @@ class Action extends HTMLOutputter // lawsuit parent::__construct($output, $indent); } + function getError() + { + return $this->error; + } + + function getInfo() + { + return $this->msg; + } + + static public function run(array $args=array(), $output='php://output', $indent=null) { + $class = get_called_class(); + $action = new $class($output, $indent); + $action->execute($args); + return $action; + } + + public function execute(array $args=array()) { + // checkMirror stuff + if (common_config('db', 'mirror') && $this->isReadOnly($args)) { + if (is_array(common_config('db', 'mirror'))) { + // "load balancing", ha ha + $arr = common_config('db', 'mirror'); + $k = array_rand($arr); + $mirror = $arr[$k]; + } else { + $mirror = common_config('db', 'mirror'); + } + + // everyone else uses the mirror + common_config_set('db', 'database', $mirror); + } + + if ($this->prepare($args)) { + $this->handle($args); + } + } + /** * For initializing members of the class. * @@ -80,14 +132,27 @@ class Action extends HTMLOutputter // lawsuit * * @return boolean true */ - function prepare($argarray) + protected function prepare(array $args=array()) { - $this->args =& common_copy_args($argarray); + if ($this->needPost && !$this->isPost()) { + $this->clientError(_('This method requires a POST.'), 405); + } + + $this->args = common_copy_args($args); - if ($this->boolean('ajax')) { + $this->action = $this->trimmed('action'); + + if ($this->ajax || $this->boolean('ajax')) { + // check with StatusNet::isAjax() StatusNet::setAjax(true); } + if ($this->needLogin) { + $this->checkLogin(); // if not logged in, this redirs/excepts + } + + $this->scoped = Profile::current(); + return true; } @@ -222,14 +287,12 @@ class Action extends HTMLOutputter // lawsuit // Use old name for StatusNet for compatibility on events - if (Event::handle('StartShowStatusNetStyles', array($this)) && - Event::handle('StartShowLaconicaStyles', array($this))) { + if (Event::handle('StartShowStylesheets', array($this))) { $this->primaryCssLink(null, 'screen, projection, tv, print'); - Event::handle('EndShowStatusNetStyles', array($this)); - Event::handle('EndShowLaconicaStyles', array($this)); + Event::handle('EndShowStylesheets', array($this)); } - $this->cssLink(common_path('js/css/smoothness/jquery-ui.css')); + $this->cssLink('js/extlib/jquery-ui/css/smoothness/jquery-ui.css'); if (Event::handle('StartShowUAStyles', array($this))) { $this->comment('[if IE]>comment('[if IE]>comment('[if IE]>viewdesigns) { - $design = $this->getDesign(); - - if (!empty($design)) { - $design->showCSS($this); - } - } - - Event::handle('EndShowDesign', array($this)); - } Event::handle('EndShowStyles', array($this)); if (common_config('custom_css', 'enabled')) { @@ -291,6 +342,13 @@ class Action extends HTMLOutputter // lawsuit $this->cssLink('css/display.css', $baseTheme, $media); } $this->cssLink('css/display.css', $mainTheme, $media); + + // Additional styles for RTL languages + if (is_rtl(common_language())) { + if (file_exists(Theme::file('css/rtl.css'))) { + $this->cssLink('css/rtl.css', $mainTheme, $media); + } + } } /** @@ -303,21 +361,19 @@ class Action extends HTMLOutputter // lawsuit if (Event::handle('StartShowScripts', array($this))) { if (Event::handle('StartShowJQueryScripts', array($this))) { if (common_config('site', 'minify')) { - $this->script('jquery.min.js'); - $this->script('jquery.form.min.js'); - $this->script('jquery-ui.min.js'); - $this->script('jquery.cookie.min.js'); - $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.min.js').'"); }'); - $this->script('jquery.joverlay.min.js'); - $this->script('jquery.infieldlabel.min.js'); + $this->script('extlib/jquery.min.js'); + $this->script('extlib/jquery.form.min.js'); + $this->script('extlib/jquery-ui/jquery-ui.min.js'); + $this->script('extlib/jquery.cookie.min.js'); + $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/extlib/json2.min.js', StatusNet::isHTTPS()).'"); }'); + $this->script('extlib/jquery.infieldlabel.min.js'); } else { - $this->script('jquery.js'); - $this->script('jquery.form.js'); - $this->script('jquery-ui.min.js'); - $this->script('jquery.cookie.js'); - $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/json2.js').'"); }'); - $this->script('jquery.joverlay.js'); - $this->script('jquery.infieldlabel.js'); + $this->script('extlib/jquery.js'); + $this->script('extlib/jquery.form.js'); + $this->script('extlib/jquery-ui/jquery-ui.js'); + $this->script('extlib/jquery.cookie.js'); + $this->inlineScript('if (typeof window.JSON !== "object") { $.getScript("'.common_path('js/extlib/json2.js', StatusNet::isHTTPS()).'"); }'); + $this->script('extlib/jquery.infieldlabel.js'); } Event::handle('EndShowJQueryScripts', array($this)); @@ -331,8 +387,10 @@ class Action extends HTMLOutputter // lawsuit $this->script('xbImportNode.js'); $this->script('geometa.js'); } + // This route isn't available in single-user mode. + // Not sure why, but it causes errors here. $this->inlineScript('var _peopletagAC = "' . - common_local_url('peopletagautocomplete') . '";'); + common_local_url('peopletagautocomplete') . '";'); $this->showScriptMessages(); // Anti-framing code to avoid clickjacking attacks in older browsers. // This will show a blank page if the page is being framed, which is @@ -373,7 +431,7 @@ class Action extends HTMLOutputter // lawsuit $messages = array_merge($messages, $this->getScriptMessages()); - Event::handle('EndScriptMessages', array($this, &$messages)); + Event::handle('EndScriptMessages', array($this, &$messages)); } if (!empty($messages)) { @@ -548,7 +606,7 @@ class Action extends HTMLOutputter // lawsuit // if logo is an uploaded file, try to fall back to HTTPS file URL $httpUrl = common_config('site', 'logo'); if (!empty($httpUrl)) { - $f = File::staticGet('url', $httpUrl); + $f = File::getKV('url', $httpUrl); if (!empty($f) && !empty($f->filename)) { // this will handle the HTTPS case $logoUrl = File::url($f->filename); @@ -587,6 +645,14 @@ class Action extends HTMLOutputter // lawsuit function showPrimaryNav() { $this->elementStart('div', array('id' => 'site_nav_global_primary')); + + $user = common_current_user(); + + if (!empty($user) || !common_config('site', 'private')) { + $form = new SearchForm($this); + $form->show(); + } + $pn = new PrimaryNav($this); $pn->show(); $this->elementEnd('div'); @@ -995,17 +1061,17 @@ class Action extends HTMLOutputter // lawsuit // TRANS: Text between [] is a link description, text between () is the link itself. // TRANS: Make sure there is no whitespace between "]" and "(". // TRANS: "%%site.broughtby%%" is the value of the variable site.broughtby - $instr = _('**%%site.name%%** is a microblogging service brought to you by [%%site.broughtby%%](%%site.broughtbyurl%%).'); + $instr = _('**%%site.name%%** is a social network, courtesy of [%%site.broughtby%%](%%site.broughtbyurl%%).'); } else { // TRANS: First sentence of the StatusNet site license. Used if 'broughtby' is not set. - $instr = _('**%%site.name%%** is a microblogging service.'); + $instr = _('**%%site.name%%** is a social network.'); } $instr .= ' '; // TRANS: Second sentence of the StatusNet site license. Mentions the StatusNet source code license. // TRANS: Make sure there is no whitespace between "]" and "(". // TRANS: Text between [] is a link description, text between () is the link itself. // TRANS: %s is the version of StatusNet that is being used. - $instr .= sprintf(_('It runs the [StatusNet](http://status.net/) microblogging software, version %s, available under the [GNU Affero General Public License](http://www.fsf.org/licensing/licenses/agpl-3.0.html).'), STATUSNET_VERSION); + $instr .= sprintf(_('It runs on [GNU social](http://www.gnu.org/software/social/), version %s, available under the [GNU Affero General Public License](http://www.fsf.org/licensing/licenses/agpl-3.0.html).'), STATUSNET_VERSION); $output = common_markup_to_html($instr); $this->raw($output); // do it @@ -1157,11 +1223,9 @@ class Action extends HTMLOutputter // lawsuit /** * Handler method * - * @param array $argarray is ignored since it's now passed in in prepare() - * * @return boolean is read only action? */ - function handle($argarray=null) + protected function handle() { header('Vary: Accept-Encoding,Cookie'); @@ -1295,26 +1359,121 @@ class Action extends HTMLOutputter // lawsuit * * @return nothing */ - function serverError($msg, $code=500) + function serverError($msg, $code=500, $format=null) { - $action = $this->trimmed('action'); - common_debug("Server error '$code' on '$action': $msg", __FILE__); - throw new ServerException($msg, $code); + if ($format === null) { + $format = $this->format; + } + + common_debug("Server error '{$code}' on '{$this->action}': {$msg}", __FILE__); + + if (!array_key_exists($code, ServerErrorAction::$status)) { + $code = 500; + } + + $status_string = ServerErrorAction::$status[$code]; + + switch ($format) { + case 'xml': + header("HTTP/1.1 {$code} {$status_string}"); + $this->initDocument('xml'); + $this->elementStart('hash'); + $this->element('error', null, $msg); + $this->element('request', null, $_SERVER['REQUEST_URI']); + $this->elementEnd('hash'); + $this->endDocument('xml'); + break; + case 'json': + if (!isset($this->callback)) { + header("HTTP/1.1 {$code} {$status_string}"); + } + $this->initDocument('json'); + $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); + print(json_encode($error_array)); + $this->endDocument('json'); + break; + default: + throw new ServerException($msg, $code); + } + + exit((int)$code); } /** * Client error * - * @param string $msg error message to display - * @param integer $code http error code, 400 by default + * @param string $msg error message to display + * @param integer $code http error code, 400 by default + * @param string $format error format (json, xml, text) for ApiAction * * @return nothing + * @throws ClientException always */ - function clientError($msg, $code=400) + function clientError($msg, $code=400, $format=null) { - $action = $this->trimmed('action'); - common_debug("User error '$code' on '$action': $msg", __FILE__); - throw new ClientException($msg, $code); + // $format is currently only relevant for an ApiAction anyway + if ($format === null) { + $format = $this->format; + } + + common_debug("User error '{$code}' on '{$this->action}': {$msg}", __FILE__); + + if (!array_key_exists($code, ClientErrorAction::$status)) { + $code = 400; + } + + $status_string = ClientErrorAction::$status[$code]; + + switch ($format) { + case 'xml': + header("HTTP/1.1 {$code} {$status_string}"); + $this->initDocument('xml'); + $this->elementStart('hash'); + $this->element('error', null, $msg); + $this->element('request', null, $_SERVER['REQUEST_URI']); + $this->elementEnd('hash'); + $this->endDocument('xml'); + break; + case 'json': + if (!isset($this->callback)) { + header("HTTP/1.1 {$code} {$status_string}"); + } + $this->initDocument('json'); + $error_array = array('error' => $msg, 'request' => $_SERVER['REQUEST_URI']); + $this->text(json_encode($error_array)); + $this->endDocument('json'); + break; + case 'text': + header("HTTP/1.1 {$code} {$status_string}"); + header('Content-Type: text/plain; charset=utf-8'); + echo $msg; + break; + default: + throw new ClientException($msg, $code); + } + exit((int)$code); + } + + /** + * If not logged in, take appropriate action (redir or exception) + * + * @param boolean $redir Redirect to login if not logged in + * + * @return boolean true if logged in (never returns if not) + */ + public function checkLogin($redir=true) + { + if (common_logged_in()) { + return true; + } + + if ($redir==true) { + common_set_returnto($_SERVER['REQUEST_URI']); + common_redirect(common_local_url('login')); + } + + // TRANS: Error message displayed when trying to perform an action that requires a logged in user. + $this->clientError(_('Not logged in.'), 403); } /** @@ -1365,15 +1524,22 @@ class Action extends HTMLOutputter // lawsuit { // Added @id to li for some control. // XXX: We might want to move this to htmloutputter.php - $lattrs = array(); + $lattrs = array(); + $classes = array(); if ($class !== null) { - $lattrs['class'] = $class; - if ($is_selected) { - $lattrs['class'] = trim('current ' . $lattrs['class']); - } + $classes[] = trim($class); + } + if ($is_selected) { + $classes[] = 'current'; } - (is_null($id)) ? $lattrs : $lattrs['id'] = $id; + if (!empty($classes)) { + $lattrs['class'] = implode(' ', $classes); + } + + if (!is_null($id)) { + $lattrs['id'] = $id; + } $this->elementStart('li', $lattrs); $attrs['href'] = $url; @@ -1442,16 +1608,6 @@ class Action extends HTMLOutputter // lawsuit return null; } - /** - * A design for this action - * - * @return Design a design object to use - */ - function getDesign() - { - return Design::siteDesign(); - } - /** * Check the session token. *