]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Merge branch 'configure-docs' into 'nightly'
authormmn <mmn@hethane.se>
Thu, 3 Sep 2015 16:11:28 +0000 (16:11 +0000)
committermmn <mmn@hethane.se>
Thu, 3 Sep 2015 16:11:28 +0000 (16:11 +0000)
Add a few missing 'attachments' config options

show_thumbs
show_html
filename_base

See merge request !27

17 files changed:
INSTALL
actions/apiaccountupdateprofile.php
actions/groupbyid.php
avatar/.gitignore [deleted file]
background/.gitignore [deleted file]
extlib/Auth/OpenID/URINorm.php
extlib/Mf2/Parser.php
file/.gitignore [deleted file]
lib/framework.php
lib/installer.php
lib/targetedrss10action.php
nginx.conf.sample [new file with mode: 0644]
plugins/ChooseTheme/ChooseThemePlugin.php [new file with mode: 0644]
plugins/ChooseTheme/README.md [new file with mode: 0644]
plugins/ChooseTheme/actions/choosethemesettings.php [new file with mode: 0644]
plugins/ChooseTheme/locale/ChooseTheme.pot [new file with mode: 0644]
plugins/ChooseTheme/locale/nb/LC_MESSAGES/ChooseTheme.po [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
index 90fa84923bb92bda257863687ef5d71455e4b51d..64f30139bf92eea2c673bdc4bccbabe9567d45e6 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -196,7 +196,9 @@ your server (like lighttpd or nginx).
         file is well commented. 
     * For lighttpd, inspect the lighttpd.conf.example file and apply the
         appropriate changes in your virtualhost configuration for lighttpd.
-    * For nginx and other webservers, we gladly accept contributions of
+    * For nginx, inspect the nginx.conf.sample file and apply the appropriate
+        changes.
+    * For other webservers, we gladly accept contributions of
         server configuration examples.
 
 2. Assuming your webserver is properly configured and have its settings
index a9842ec5d8f33d80dba29e353e4597be3150623c..8767dabf8528a6ef23c597bb7b4a8de47903ba8a 100644 (file)
@@ -96,21 +96,12 @@ class ApiAccountUpdateProfileAction extends ApiAuthAction
 
         $original = clone($profile);
 
-        if (!empty($this->name)) {
-            $profile->fullname = $this->name;
-        }
-
-        if (!empty($this->url)) {
-            $profile->homepage = $this->url;
-        }
-
-        if (!empty($this->description)) {
-            $profile->bio = $this->description;
-        }
+        $profile->fullname = $this->name;
+        $profile->homepage = $this->url;
+        $profile->bio = $this->description;
+        $profile->location = $this->location;
 
         if (!empty($this->location)) {
-            $profile->location = $this->location;
-
             $loc = Location::fromName($this->location);
 
             if (!empty($loc)) {
@@ -119,6 +110,12 @@ class ApiAccountUpdateProfileAction extends ApiAuthAction
                 $profile->location_id = $loc->location_id;
                 $profile->location_ns = $loc->location_ns;
             }
+        } else {
+            // location is empty so reset the extrapolated information too
+            $profile->lat = '';
+            $profile->lon = '';
+            $profile->location_id = '';
+            $profile->location_ns = '';
         }
 
         $result = $profile->update($original);
index 8556675155262dc61d51c072c671409f3b3aba87..de87ec5c672e20da7632ef8f29e99c9411e4a91a 100644 (file)
@@ -42,53 +42,22 @@ if (!defined('GNUSOCIAL')) { exit(1); }
  * @license  http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
  * @link     http://status.net/
  */
-class GroupbyidAction extends Action
+class GroupbyidAction extends ManagedAction
 {
     /** group we're viewing. */
-    var $group = null;
+    protected $group = null;
 
-    /**
-     * Is this page read-only?
-     *
-     * @return boolean true
-     */
     function isReadOnly($args)
     {
         return true;
     }
 
-    function prepare($args)
+    protected function doPreparation()
     {
-        parent::prepare($args);
-
-        $id = $this->arg('id');
-
-        if (!$id) {
-            // TRANS: Client error displayed referring to a group's permalink without providing a group ID.
-            $this->clientError(_('No ID.'));
-        }
-
-        common_debug("Got ID $id");
-
-        $this->group = User_group::getKV('id', $id);
-
-        if (!$this->group) {
-            // TRANS: Client error displayed referring to a group's permalink for a non-existing group ID.
-            $this->clientError(_('No such group.'), 404);
-        }
-
-        return true;
+        $this->group = User_group::getByID($this->arg('id'));
     }
 
-    /**
-     * Handle the request
-     *
-     * Shows a profile for the group, some controls, and a list of
-     * group notices.
-     *
-     * @return void
-     */
-    function handle($args)
+    public function showPage()
     {
         common_redirect($this->group->homeUrl(), 303);
     }
diff --git a/avatar/.gitignore b/avatar/.gitignore
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/background/.gitignore b/background/.gitignore
deleted file mode 100644 (file)
index e69de29..0000000
index c051b550aa1b1e3d339cb7110f6bc80ddedaa8d8..32e84588dbe77f55f7daeb849163bb946a26c40c 100644 (file)
@@ -93,7 +93,17 @@ function Auth_OpenID_pct_encoded_replace_unreserved($mo)
 
 function Auth_OpenID_pct_encoded_replace($mo)
 {
-    return chr(intval($mo[1], 16));
+    $code = intval($mo[1], 16);
+
+    // Prevent request splitting by ignoring newline and space characters
+    if($code === 0xA || $code === 0xD || $code === ord(' '))
+    {
+        return $mo[0];
+    }
+    else
+    {
+        return chr($code);
+    }
 }
 
 function Auth_OpenID_remove_dot_segments($path)
index 27805f2324e54b0802e7f6a18d053be15ac98bff..b8a954f2c8631f965c7880b45ec5c2e67f29da0e 100644 (file)
@@ -13,17 +13,17 @@ use stdClass;
 
 /**
  * Parse Microformats2
- * 
+ *
  * Functional shortcut for the commonest cases of parsing microformats2 from HTML.
- * 
+ *
  * Example usage:
- * 
+ *
  *     use Mf2;
  *     $output = Mf2\parse('<span class="h-card">Barnaby Walters</span>');
  *     echo json_encode($output, JSON_PRETTY_PRINT);
- * 
+ *
  * Produces:
- * 
+ *
  *     {
  *      "items": [
  *       {
@@ -35,7 +35,7 @@ use stdClass;
  *      ],
  *      "rels": {}
  *     }
- * 
+ *
  * @param string|DOMDocument $input The HTML string or DOMDocument object to parse
  * @param string $url The URL the input document was found at, for relative URL resolution
  * @param bool $convertClassic whether or not to convert classic microformats
@@ -84,7 +84,7 @@ function fetch($url, $convertClassic = true, &$curlInfo=null) {
 /**
  * Unicode to HTML Entities
  * @param string $input String containing characters to convert into HTML entities
- * @return string 
+ * @return string
  */
 function unicodeToHtmlEntities($input) {
        return mb_convert_encoding($input, 'HTML-ENTITIES', mb_detect_encoding($input));
@@ -92,10 +92,10 @@ function unicodeToHtmlEntities($input) {
 
 /**
  * Collapse Whitespace
- * 
+ *
  * Collapses any sequences of whitespace within a string into a single space
  * character.
- * 
+ *
  * @deprecated since v0.2.3
  * @param string $str
  * @return string
@@ -113,10 +113,10 @@ function unicodeTrim($str) {
 
 /**
  * Microformat Name From Class string
- * 
- * Given the value of @class, get the relevant mf classnames (e.g. h-card, 
+ *
+ * Given the value of @class, get the relevant mf classnames (e.g. h-card,
  * p-name).
- * 
+ *
  * @param string $class A space delimited list of classnames
  * @param string $prefix The prefix to look for
  * @return string|array The prefixed name of the first microfomats class found or false
@@ -127,9 +127,9 @@ function mfNamesFromClass($class, $prefix='h-') {
        $matches = array();
 
        foreach ($classes as $classname) {
-               $compare_classname = strtolower(' ' . $classname);
-               $compare_prefix = strtolower(' ' . $prefix);
-               if (stristr($compare_classname, $compare_prefix) !== false && ($compare_classname != $compare_prefix)) {
+               $compare_classname = ' ' . $classname;
+               $compare_prefix = ' ' . $prefix;
+               if (strstr($compare_classname, $compare_prefix) !== false && ($compare_classname != $compare_prefix)) {
                        $matches[] = ($prefix === 'h-') ? $classname : substr($classname, strlen($prefix));
                }
        }
@@ -139,10 +139,10 @@ function mfNamesFromClass($class, $prefix='h-') {
 
 /**
  * Get Nested µf Property Name From Class
- * 
- * Returns all the p-, u-, dt- or e- prefixed classnames it finds in a 
+ *
+ * Returns all the p-, u-, dt- or e- prefixed classnames it finds in a
  * space-separated string.
- * 
+ *
  * @param string $class
  * @return array
  */
@@ -153,19 +153,24 @@ function nestedMfPropertyNamesFromClass($class) {
        $class = str_replace(array(' ', '       ', "\n"), ' ', $class);
        foreach (explode(' ', $class) as $classname) {
                foreach ($prefixes as $prefix) {
-                       $compare_classname = strtolower(' ' . $classname);
-                       if (stristr($compare_classname, $prefix) && ($compare_classname != $prefix)) {
-                               $propertyNames = array_merge($propertyNames, mfNamesFromClass($classname, ltrim($prefix)));
+                       // Check if $classname is a valid property classname for $prefix.
+                       if (mb_substr($classname, 0, mb_strlen($prefix)) == $prefix && $classname != $prefix) {
+                               $propertyName = mb_substr($classname, mb_strlen($prefix));
+                               $propertyNames[$propertyName][] = $prefix;
                        }
                }
        }
+       
+       foreach ($propertyNames as $property => $prefixes) {
+               $propertyNames[$property] = array_unique($prefixes);
+       }
 
        return $propertyNames;
 }
 
 /**
  * Wraps mfNamesFromClass to handle an element as input (common)
- * 
+ *
  * @param DOMElement $e The element to get the classname for
  * @param string $prefix The prefix to look for
  * @return mixed See return value of mf2\Parser::mfNameFromClass()
@@ -192,28 +197,27 @@ function convertTimeFormat($time) {
        $hh = $mm = $ss = '';
        preg_match('/(\d{1,2}):?(\d{2})?:?(\d{2})?(a\.?m\.?|p\.?m\.?)?/i', $time, $matches);
 
-       // if no am/pm specified
+       // If no am/pm is specified:
        if (empty($matches[4])) {
                return $time;
-       }
-       // else am/pm specified
-       else {
+       } else {
+               // Otherwise, am/pm is specified.
                $meridiem = strtolower(str_replace('.', '', $matches[4]));
 
-               // hours
+               // Hours.
                $hh = $matches[1];
 
-               // add 12 to the pm hours
+               // Add 12 to hours if pm applies.
                if ($meridiem == 'pm' && ($hh < 12)) {
                        $hh += 12;
                }
 
                $hh = str_pad($hh, 2, '0', STR_PAD_LEFT);
 
-               // minutes
+               // Minutes.
                $mm = (empty($matches[2]) ) ? '00' : $matches[2];
 
-               // seconds, only if supplied
+               // Seconds, only if supplied.
                if (!empty($matches[3])) {
                        $ss = $matches[3];
                }
@@ -229,11 +233,11 @@ function convertTimeFormat($time) {
 
 /**
  * Microformats2 Parser
- * 
+ *
  * A class which holds state for parsing microformats2 from HTML.
- * 
+ *
  * Example usage:
- * 
+ *
  *     use Mf2;
  *     $parser = new Mf2\Parser('<p class="h-card">Barnaby Walters</p>');
  *     $output = $parser->parse();
@@ -244,18 +248,18 @@ class Parser {
 
        /** @var DOMXPath object which can be used to query over any fragment*/
        public $xpath;
-       
+
        /** @var DOMDocument */
        public $doc;
-       
+
        /** @var SplObjectStorage */
        protected $parsed;
-       
+
        public $jsonMode;
 
        /**
         * Constructor
-        * 
+        *
         * @param DOMDocument|string $input The data to parse. A string of HTML or a DOMDocument
         * @param string $url The URL of the parsed document, for relative URL resolution
         * @param boolean $jsonMode Whether or not to use a stdClass instance for an empty `rels` dictionary. This breaks PHP looping over rels, but allows the output to be correctly serialized as JSON.
@@ -271,20 +275,20 @@ class Parser {
                        $doc = new DOMDocument();
                        @$doc->loadHTML('');
                }
-               
+
                $this->xpath = new DOMXPath($doc);
-               
+
                $baseurl = $url;
                foreach ($this->xpath->query('//base[@href]') as $base) {
                        $baseElementUrl = $base->getAttribute('href');
-                       
+
                        if (parse_url($baseElementUrl, PHP_URL_SCHEME) === null) {
                                /* The base element URL is relative to the document URL.
                                 *
                                 * :/
                                 *
                                 * Perhaps the author was high? */
-                               
+
                                $baseurl = resolveUrl($url, $baseElementUrl);
                        } else {
                                $baseurl = $baseElementUrl;
@@ -296,31 +300,31 @@ class Parser {
                foreach ($this->xpath->query('//template') as $templateEl) {
                        $templateEl->parentNode->removeChild($templateEl);
                }
-               
+
                $this->baseurl = $baseurl;
                $this->doc = $doc;
                $this->parsed = new SplObjectStorage();
                $this->jsonMode = $jsonMode;
        }
-       
+
        private function elementPrefixParsed(\DOMElement $e, $prefix) {
                if (!$this->parsed->contains($e))
                        $this->parsed->attach($e, array());
-               
+
                $prefixes = $this->parsed[$e];
                $prefixes[] = $prefix;
                $this->parsed[$e] = $prefixes;
        }
-       
+
        private function isElementParsed(\DOMElement $e, $prefix) {
                if (!$this->parsed->contains($e))
                        return false;
-               
+
                $prefixes = $this->parsed[$e];
-               
+
                if (!in_array($prefix, $prefixes))
                        return false;
-               
+
                return true;
        }
 
@@ -352,72 +356,72 @@ class Parser {
 
        // TODO: figure out if this has problems with sms: and geo: URLs
        public function resolveUrl($url) {
-               // If the URL is seriously malformed it’s probably beyond the scope of this 
+               // If the URL is seriously malformed it’s probably beyond the scope of this
                // parser to try to do anything with it.
                if (parse_url($url) === false)
                        return $url;
-               
+
                $scheme = parse_url($url, PHP_URL_SCHEME);
-               
+
                if (empty($scheme) and !empty($this->baseurl)) {
                        return resolveUrl($this->baseurl, $url);
                } else {
                        return $url;
                }
        }
-       
+
        // Parsing Functions
-       
+
        /**
-        * Parse value-class/value-title on an element, joining with $separator if 
+        * Parse value-class/value-title on an element, joining with $separator if
         * there are multiple.
-        * 
+        *
         * @param \DOMElement $e
         * @param string $separator = '' if multiple value-title elements, join with this string
         * @return string|null the parsed value or null if value-class or -title aren’t in use
         */
        public function parseValueClassTitle(\DOMElement $e, $separator = '') {
                $valueClassElements = $this->xpath->query('./*[contains(concat(" ", @class, " "), " value ")]', $e);
-               
+
                if ($valueClassElements->length !== 0) {
                        // Process value-class stuff
                        $val = '';
                        foreach ($valueClassElements as $el) {
                                $val .= $this->textContent($el);
                        }
-                       
+
                        return unicodeTrim($val);
                }
-               
+
                $valueTitleElements = $this->xpath->query('./*[contains(concat(" ", @class, " "), " value-title ")]', $e);
-               
+
                if ($valueTitleElements->length !== 0) {
                        // Process value-title stuff
                        $val = '';
                        foreach ($valueTitleElements as $el) {
                                $val .= $el->getAttribute('title');
                        }
-                       
+
                        return unicodeTrim($val);
                }
-               
+
                // No value-title or -class in this element
                return null;
        }
-       
+
        /**
         * Given an element with class="p-*", get it’s value
-        * 
+        *
         * @param DOMElement $p The element to parse
         * @return string The plaintext value of $p, dependant on type
         * @todo Make this adhere to value-class
         */
        public function parseP(\DOMElement $p) {
                $classTitle = $this->parseValueClassTitle($p, ' ');
-               
+
                if ($classTitle !== null)
                        return $classTitle;
-               
+
                if ($p->tagName == 'img' and $p->getAttribute('alt') !== '') {
                        $pValue = $p->getAttribute('alt');
                } elseif ($p->tagName == 'area' and $p->getAttribute('alt') !== '') {
@@ -429,13 +433,13 @@ class Parser {
                } else {
                        $pValue = unicodeTrim($this->textContent($p));
                }
-               
+
                return $pValue;
        }
 
        /**
         * Given an element with class="u-*", get the value of the URL
-        * 
+        *
         * @param DOMElement $u The element to parse
         * @return string The plaintext value of $u, dependant on type
         * @todo make this adhere to value-class
@@ -443,18 +447,18 @@ class Parser {
        public function parseU(\DOMElement $u) {
                if (($u->tagName == 'a' or $u->tagName == 'area') and $u->getAttribute('href') !== null) {
                        $uValue = $u->getAttribute('href');
-               } elseif ($u->tagName == 'img' and $u->getAttribute('src') !== null) {
+               } elseif (in_array($u->tagName, array('img', 'audio', 'video', 'source')) and $u->getAttribute('src') !== null) {
                        $uValue = $u->getAttribute('src');
                } elseif ($u->tagName == 'object' and $u->getAttribute('data') !== null) {
                        $uValue = $u->getAttribute('data');
                }
-               
+
                if (isset($uValue)) {
                        return $this->resolveUrl($uValue);
                }
-               
+
                $classTitle = $this->parseValueClassTitle($u);
-               
+
                if ($classTitle !== null) {
                        return $classTitle;
                } elseif ($u->tagName == 'abbr' and $u->getAttribute('title') !== null) {
@@ -468,7 +472,7 @@ class Parser {
 
        /**
         * Given an element with class="dt-*", get the value of the datetime as a php date object
-        * 
+        *
         * @param DOMElement $dt The element to parse
         * @param array $dates Array of dates processed so far
         * @return string The datetime string found
@@ -477,11 +481,11 @@ class Parser {
                // Check for value-class pattern
                $valueClassChildren = $this->xpath->query('./*[contains(concat(" ", @class, " "), " value ") or contains(concat(" ", @class, " "), " value-title ")]', $dt);
                $dtValue = false;
-               
+
                if ($valueClassChildren->length > 0) {
                        // They’re using value-class
                        $dateParts = array();
-                       
+
                        foreach ($valueClassChildren as $e) {
                                if (strstr(' ' . $e->getAttribute('class') . ' ', ' value-title ')) {
                                        $title = $e->getAttribute('title');
@@ -591,16 +595,16 @@ class Parser {
                                $dtValue = $dt->nodeValue;
                        }
 
-                       if ( preg_match('/(\d{4}-\d{2}-\d{2})/', $dtValue, $matches) ) {
+                       if (preg_match('/(\d{4}-\d{2}-\d{2})/', $dtValue, $matches)) {
                                $dates[] = $matches[0];
                        }
                }
 
                /**
-                * if $dtValue is only a time and there are recently parsed dates, 
-                * form the full date-time using the most recnetly parsed dt- value
+                * if $dtValue is only a time and there are recently parsed dates,
+                * form the full date-time using the most recently parsed dt- value
                 */
-               if ( (preg_match('/^\d{1,2}:\d{1,2}(Z?[+|-]\d{2}:?\d{2})?/', $dtValue) or preg_match('/^\d{1,2}[a|p]m/', $dtValue)) && !empty($dates) ) {
+               if ((preg_match('/^\d{1,2}:\d{1,2}(Z?[+|-]\d{2}:?\d{2})?/', $dtValue) or preg_match('/^\d{1,2}[a|p]m/', $dtValue)) && !empty($dates)) {
                        $dtValue = convertTimeFormat($dtValue);
                        $dtValue = end($dates) . 'T' . unicodeTrim($dtValue, 'T');
                }
@@ -613,15 +617,15 @@ class Parser {
         *
         *      @param DOMElement $e The element to parse
         *      @return string $e’s innerHTML
-        * 
+        *
         * @todo need to mark this element as e- parsed so it doesn’t get parsed as it’s parent’s e-* too
         */
        public function parseE(\DOMElement $e) {
                $classTitle = $this->parseValueClassTitle($e);
-               
+
                if ($classTitle !== null)
                        return $classTitle;
-               
+
                // Expand relative URLs within children of this element
                // TODO: as it is this is not relative to only children, make this .// and rerun tests
                $this->resolveChildUrls($e);
@@ -630,7 +634,7 @@ class Parser {
                foreach ($e->childNodes as $node) {
                        $html .= $node->C14N();
                }
-               
+
                return array(
                        'html' => $html,
                        'value' => unicodeTrim($this->textContent($e))
@@ -639,7 +643,7 @@ class Parser {
 
        /**
         * Recursively parse microformats
-        * 
+        *
         * @param DOMElement $e The element to parse
         * @return array A representation of the values contained within microformat $e
         */
@@ -660,26 +664,39 @@ class Parser {
                foreach ($this->xpath->query('.//*[contains(concat(" ", @class)," h-")]', $e) as $subMF) {
                        // Parse
                        $result = $this->parseH($subMF);
-                       
+
                        // If result was already parsed, skip it
                        if (null === $result)
                                continue;
                        
+                       // In most cases, the value attribute of the nested microformat should be the p- parsed value of the elemnt.
+                       // The only times this is different is when the microformat is nested under certain prefixes, which are handled below.
                        $result['value'] = $this->parseP($subMF);
 
                        // Does this µf have any property names other than h-*?
                        $properties = nestedMfPropertyNamesFromElement($subMF);
-                       
+
                        if (!empty($properties)) {
                                // Yes! It’s a nested property µf
-                               foreach ($properties as $property) {
-                                       $return[$property][] = $result;
+                               foreach ($properties as $property => $prefixes) {
+                                       // Note: handling microformat nesting under multiple conflicting prefixes is not currently specified by the mf2 parsing spec.
+                                       $prefixSpecificResult = $result;
+                                       if (in_array('p-', $prefixes)) {
+                                               $prefixSpecificResult['value'] = $prefixSpecificResult['properties']['name'][0];
+                                       } elseif (in_array('e-', $prefixes)) {
+                                               $eParsedResult = $this->parseE($subMF);
+                                               $prefixSpecificResult['html'] = $eParsedResult['html'];
+                                               $prefixSpecificResult['value'] = $eParsedResult['value'];
+                                       } elseif (in_array('u-', $prefixes)) {
+                                               $prefixSpecificResult['value'] = $this->parseU($subMF);
+                                       }
+                                       $return[$property][] = $prefixSpecificResult;
                                }
                        } else {
                                // No, it’s a child µf
                                $children[] = $result;
                        }
-                       
+
                        // Make sure this sub-mf won’t get parsed as a µf or property
                        // TODO: Determine if clearing this is required?
                        $this->elementPrefixParsed($subMF, 'h');
@@ -689,19 +706,24 @@ class Parser {
                        $this->elementPrefixParsed($subMF, 'e');
                }
 
+               if($e->tagName == 'area') {
+                       $coords = $e->getAttribute('coords');
+                       $shape = $e->getAttribute('shape');
+               }
+
                // Handle p-*
                foreach ($this->xpath->query('.//*[contains(concat(" ", @class) ," p-")]', $e) as $p) {
                        if ($this->isElementParsed($p, 'p'))
                                continue;
 
                        $pValue = $this->parseP($p);
-                       
+
                        // Add the value to the array for it’s p- properties
                        foreach (mfNamesFromElement($p, 'p-') as $propName) {
                                if (!empty($propName))
                                        $return[$propName][] = $pValue;
                        }
-                       
+
                        // Make sure this sub-mf won’t get parsed as a top level mf
                        $this->elementPrefixParsed($p, 'p');
                }
@@ -710,32 +732,32 @@ class Parser {
                foreach ($this->xpath->query('.//*[contains(concat(" ",  @class)," u-")]', $e) as $u) {
                        if ($this->isElementParsed($u, 'u'))
                                continue;
-                       
+
                        $uValue = $this->parseU($u);
-                       
+
                        // Add the value to the array for it’s property types
                        foreach (mfNamesFromElement($u, 'u-') as $propName) {
                                $return[$propName][] = $uValue;
                        }
-                       
+
                        // Make sure this sub-mf won’t get parsed as a top level mf
                        $this->elementPrefixParsed($u, 'u');
                }
-               
+
                // Handle dt-*
                foreach ($this->xpath->query('.//*[contains(concat(" ", @class), " dt-")]', $e) as $dt) {
                        if ($this->isElementParsed($dt, 'dt'))
                                continue;
-                       
+
                        $dtValue = $this->parseDT($dt, $dates);
-                       
+
                        if ($dtValue) {
                                // Add the value to the array for dt- properties
                                foreach (mfNamesFromElement($dt, 'dt-') as $propName) {
                                        $return[$propName][] = $dtValue;
                                }
                        }
-                       
+
                        // Make sure this sub-mf won’t get parsed as a top level mf
                        $this->elementPrefixParsed($dt, 'dt');
                }
@@ -762,22 +784,43 @@ class Parser {
                if (!array_key_exists('name', $return)) {
                        try {
                                // Look for img @alt
-                               if ($e->tagName == 'img' and $e->getAttribute('alt') != '')
+                               if (($e->tagName == 'img' or $e->tagName == 'area') and $e->getAttribute('alt') != '')
                                        throw new Exception($e->getAttribute('alt'));
-                               
+
                                if ($e->tagName == 'abbr' and $e->hasAttribute('title'))
                                        throw new Exception($e->getAttribute('title'));
-                               
+
                                // Look for nested img @alt
                                foreach ($this->xpath->query('./img[count(preceding-sibling::*)+count(following-sibling::*)=0]', $e) as $em) {
-                                       if ($em->getAttribute('alt') != '')
+                                       $emNames = mfNamesFromElement($em, 'h-');
+                                       if (empty($emNames) && $em->getAttribute('alt') != '') {
                                                throw new Exception($em->getAttribute('alt'));
+                                       }
+                               }
+
+                               // Look for nested area @alt
+                               foreach ($this->xpath->query('./area[count(preceding-sibling::*)+count(following-sibling::*)=0]', $e) as $em) {
+                                       $emNames = mfNamesFromElement($em, 'h-');
+                                       if (empty($emNames) && $em->getAttribute('alt') != '') {
+                                               throw new Exception($em->getAttribute('alt'));
+                                       }
                                }
 
+
                                // Look for double nested img @alt
                                foreach ($this->xpath->query('./*[count(preceding-sibling::*)+count(following-sibling::*)=0]/img[count(preceding-sibling::*)+count(following-sibling::*)=0]', $e) as $em) {
-                                       if ($em->getAttribute('alt') != '')
+                                       $emNames = mfNamesFromElement($em, 'h-');
+                                       if (empty($emNames) && $em->getAttribute('alt') != '') {
+                                               throw new Exception($em->getAttribute('alt'));
+                                       }
+                               }
+
+                               // Look for double nested img @alt
+                               foreach ($this->xpath->query('./*[count(preceding-sibling::*)+count(following-sibling::*)=0]/area[count(preceding-sibling::*)+count(following-sibling::*)=0]', $e) as $em) {
+                                       $emNames = mfNamesFromElement($em, 'h-');
+                                       if (empty($emNames) && $em->getAttribute('alt') != '') {
                                                throw new Exception($em->getAttribute('alt'));
+                                       }
                                }
 
                                throw new Exception($e->nodeValue);
@@ -812,36 +855,58 @@ class Parser {
                // Check for u-url
                if (!array_key_exists('url', $return)) {
                        // Look for img @src
-                       if ($e->tagName == 'a')
+                       if ($e->tagName == 'a' or $e->tagName == 'area')
                                $url = $e->getAttribute('href');
-                       
-                       // Look for nested img @src
+
+                       // Look for nested a @href
                        foreach ($this->xpath->query('./a[count(preceding-sibling::a)+count(following-sibling::a)=0]', $e) as $em) {
-                               $url = $em->getAttribute('href');
-                               break;
+                               $emNames = mfNamesFromElement($em, 'h-');
+                               if (empty($emNames)) {
+                                       $url = $em->getAttribute('href');
+                                       break;
+                               }
                        }
-                       
+
+                       // Look for nested area @src
+                       foreach ($this->xpath->query('./area[count(preceding-sibling::area)+count(following-sibling::area)=0]', $e) as $em) {
+                               $emNames = mfNamesFromElement($em, 'h-');
+                               if (empty($emNames)) {
+                                       $url = $em->getAttribute('href');
+                                       break;
+                               }
+                       }
+
                        if (!empty($url))
                                $return['url'][] = $this->resolveUrl($url);
                }
 
                // Make sure things are in alphabetical order
                sort($mfTypes);
-               
+
                // Phew. Return the final result.
                $parsed = array(
                        'type' => $mfTypes,
                        'properties' => $return
                );
-               if (!empty($children))
+
+               if (!empty($shape)) {
+                       $parsed['shape'] = $shape;
+               }
+
+               if (!empty($coords)) {
+                       $parsed['coords'] = $coords;
+               }
+
+               if (!empty($children)) {
                        $parsed['children'] = array_values(array_filter($children));
+               }
                return $parsed;
        }
-       
+
        /**
         * Parse Rels and Alternatives
-        * 
-        * Returns [$rels, $alternatives]. If the $rels value is to be empty, i.e. there are no links on the page 
+        *
+        * Returns [$rels, $alternatives]. If the $rels value is to be empty, i.e. there are no links on the page
         * with a rel value *not* containing `alternate`, then the type of $rels depends on $this->jsonMode. If set
         * to true, it will be a stdClass instance, optimising for JSON serialisation. Otherwise (the default case),
         * it will be an empty array.
@@ -849,18 +914,18 @@ class Parser {
        public function parseRelsAndAlternates() {
                $rels = array();
                $alternates = array();
-               
+
                // Iterate through all a, area and link elements with rel attributes
                foreach ($this->xpath->query('//*[@rel and @href]') as $hyperlink) {
                        if ($hyperlink->getAttribute('rel') == '')
                                continue;
-                       
+
                        // Resolve the href
                        $href = $this->resolveUrl($hyperlink->getAttribute('href'));
-                       
+
                        // Split up the rel into space-separated values
                        $linkRels = array_filter(explode(' ', $hyperlink->getAttribute('rel')));
-                       
+
                        // If alternate in rels, create alternate structure, append
                        if (in_array('alternate', $linkRels)) {
                                $alt = array(
@@ -869,10 +934,19 @@ class Parser {
                                );
                                if ($hyperlink->hasAttribute('media'))
                                        $alt['media'] = $hyperlink->getAttribute('media');
-                               
+
                                if ($hyperlink->hasAttribute('hreflang'))
                                        $alt['hreflang'] = $hyperlink->getAttribute('hreflang');
-                               
+
+                               if ($hyperlink->hasAttribute('title'))
+                                       $alt['title'] = $hyperlink->getAttribute('title');
+
+                               if ($hyperlink->hasAttribute('type'))
+                                       $alt['type'] = $hyperlink->getAttribute('type');
+
+                               if ($hyperlink->nodeValue)
+                                       $alt['text'] = $hyperlink->nodeValue;
+
                                $alternates[] = $alt;
                        } else {
                                foreach ($linkRels as $rel) {
@@ -880,38 +954,38 @@ class Parser {
                                }
                        }
                }
-               
+
                if (empty($rels) and $this->jsonMode) {
                        $rels = new stdClass();
                }
-               
+
                return array($rels, $alternates);
        }
-       
+
        /**
         * Kicks off the parsing routine
-        * 
+        *
         * If `$htmlSafe` is set, any angle brackets in the results from non e-* properties
         * will be HTML-encoded, bringing all output to the same level of encoding.
-        * 
+        *
         * If a DOMElement is set as the $context, only descendants of that element will
         * be parsed for microformats.
-        * 
+        *
         * @param bool $htmlSafe whether or not to html-encode non e-* properties. Defaults to false
         * @param DOMElement $context optionally an element from which to parse microformats
         * @return array An array containing all the µfs found in the current document
         */
        public function parse($convertClassic = true, DOMElement $context = null) {
                $mfs = array();
-               
+
                if ($convertClassic) {
                        $this->convertLegacy();
                }
-               
+
                $mfElements = null === $context
                        ? $this->xpath->query('//*[contains(concat(" ", @class), " h-")]')
                        : $this->xpath->query('.//*[contains(concat(" ",        @class), " h-")]', $context);
-               
+
                // Parser microformats
                foreach ($mfElements as $node) {
                        // For each microformat
@@ -920,64 +994,64 @@ class Parser {
                        // Add the value to the array for this property type
                        $mfs[] = $result;
                }
-               
+
                // Parse rels
                list($rels, $alternates) = $this->parseRelsAndAlternates();
-               
+
                $top = array(
                        'items' => array_values(array_filter($mfs)),
                        'rels' => $rels
                );
-               
+
                if (count($alternates))
                        $top['alternates'] = $alternates;
-               
+
                return $top;
        }
-       
+
        /**
         * Parse From ID
-        * 
+        *
         * Given an ID, parse all microformats which are children of the element with
         * that ID.
-        * 
+        *
         * Note that rel values are still document-wide.
-        * 
-        * If an element with the ID is not found, an empty skeleton mf2 array structure 
+        *
+        * If an element with the ID is not found, an empty skeleton mf2 array structure
         * will be returned.
-        * 
+        *
         * @param string $id
         * @param bool $htmlSafe = false whether or not to HTML-encode angle brackets in non e-* properties
         * @return array
         */
        public function parseFromId($id, $convertClassic=true) {
                $matches = $this->xpath->query("//*[@id='{$id}']");
-               
+
                if (empty($matches))
                        return array('items' => array(), 'rels' => array(), 'alternates' => array());
-               
+
                return $this->parse($convertClassic, $matches->item(0));
        }
 
        /**
         * Convert Legacy Classnames
-        * 
+        *
         * Adds microformats2 classnames into a document containing only legacy
         * semantic classnames.
-        * 
+        *
         * @return Parser $this
         */
        public function convertLegacy() {
                $doc = $this->doc;
                $xp = new DOMXPath($doc);
-               
+
                // replace all roots
                foreach ($this->classicRootMap as $old => $new) {
                        foreach ($xp->query('//*[contains(concat(" ", @class, " "), " ' . $old . ' ") and not(contains(concat(" ", @class, " "), " ' . $new . ' "))]') as $el) {
                                $el->setAttribute('class', $el->getAttribute('class') . ' ' . $new);
                        }
                }
-               
+
                foreach ($this->classicPropertyMap as $oldRoot => $properties) {
                        $newRoot = $this->classicRootMap[$oldRoot];
                        foreach ($properties as $old => $new) {
@@ -986,16 +1060,16 @@ class Parser {
                                }
                        }
                }
-               
+
                return $this;
        }
-       
+
        /**
         * XPath Query
-        * 
+        *
         * Runs an XPath query over the current document. Works in exactly the same
         * way as DOMXPath::query.
-        * 
+        *
         * @param string $expression
         * @param DOMNode $context
         * @return DOMNodeList
@@ -1003,7 +1077,7 @@ class Parser {
        public function query($expression, $context = null) {
                return $this->xpath->query($expression, $context);
        }
-       
+
        /**
         * Classic Root Classname map
         */
@@ -1013,11 +1087,11 @@ class Parser {
                'hentry' => 'h-entry',
                'hrecipe' => 'h-recipe',
                'hresume' => 'h-resume',
-               'hevent' => 'h-event',
+               'vevent' => 'h-event',
                'hreview' => 'h-review',
                'hproduct' => 'h-product'
        );
-       
+
        public $classicPropertyMap = array(
                'vcard' => array(
                        'fn' => 'p-name',
@@ -1084,7 +1158,7 @@ class Parser {
                        'skill' => 'p-skill',
                        'affiliation' => 'p-affiliation h-card',
                ),
-               'hevent' => array(
+               'vevent' => array(
                        'dtstart' => 'dt-start',
                        'dtend' => 'dt-end',
                        'duration' => 'dt-duration',
@@ -1246,7 +1320,7 @@ function resolveUrl($baseURI, $referenceURI) {
 # 5.2.3 Merge Paths
 function mergePaths($base, $reference) {
        # If the base URI has a defined authority component and an empty
-       #    path, 
+       #    path,
        if($base['authority'] && $base['path'] == null) {
                # then return a string consisting of "/" concatenated with the
                # reference's path; otherwise,
diff --git a/file/.gitignore b/file/.gitignore
deleted file mode 100644 (file)
index e69de29..0000000
index 1834c3e786ca8d0c5870bd8d3fc52f9d17b3d6e4..d749d23bdff32c8e3144ffb4322f7ebd232dc3c2 100644 (file)
@@ -137,9 +137,18 @@ spl_autoload_register('GNUsocial_class_autoload');
  * and is available here: http://www.php-fig.org/psr/psr-0/
 */
 spl_autoload_register(function($class){
-    $file = INSTALLDIR.'/extlib/'.preg_replace('{\\\\|_(?!.*\\\\)}', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
+    $class_path = preg_replace('{\\\\|_(?!.*\\\\)}', DIRECTORY_SEPARATOR, ltrim($class, '\\')).'.php';
+    $file = INSTALLDIR.'/extlib/'.$class_path;
     if (file_exists($file)) {
         require_once $file;
+        return;
+    }
+
+    # Try if the system has this external library
+    $file = '/usr/share/php/'.$class_path;
+    if (file_exists($file)) {
+        require_once $file;
+        return;
     }
 });
 
index 0a46b2a50815e697647d7c87371d9faf3bcf0b42..29a43833022c902ecaf7e0c0bd00e4de6e10a738 100644 (file)
@@ -622,7 +622,7 @@ abstract class Installer
 
         $this->updateStatus("GNU social has been installed at $link");
         $this->updateStatus(
-            '<strong>DONE!</strong> You can visit your <a href="'.htmlspecialchars($link).'">new GNU social site</a> (log in as "'.htmlspecialchars($this->adminNick).'"). If this is your first GNU social install, make your experience the best possible by visiting our resource site to join the <a href="https://gnu.io/social/resources/">mailing list or IRC.</a>. <a href="'.htmlspecialchars($link).'/doc/faq/">FAQ is found here</a>.'
+            '<strong>DONE!</strong> You can visit your <a href="'.htmlspecialchars($link).'">new GNU social site</a> (log in as "'.htmlspecialchars($this->adminNick).'"). If this is your first GNU social install, make your experience the best possible by visiting our resource site to join the <a href="https://gnu.io/social/resources/">mailing list or IRC</a>. <a href="'.htmlspecialchars($link).'/doc/faq">FAQ is found here</a>.'
         );
 
         return true;
index c7615bd36a6ef78c56a998e3d76c376d1b441a4c..ed7e2626236eb048b202040b0914e90aff3dbade 100644 (file)
@@ -39,6 +39,11 @@ class TargetedRss10Action extends Rss10Action
         $this->target = User::getByNickname($this->trimmed('nickname'))->getProfile();
     }
 
+    public function getTarget()
+    {
+        return $this->target;
+    }
+
     function getImage()
     {
         return $this->target->avatarUrl(AVATAR_PROFILE_SIZE);
diff --git a/nginx.conf.sample b/nginx.conf.sample
new file mode 100644 (file)
index 0000000..d05c676
--- /dev/null
@@ -0,0 +1,53 @@
+server {
+  # Ports
+  listen 80;
+  # Uncomment the following line
+  # to enable HTTPS
+  #listen 443 ssl;
+
+  # Server name
+  # Change "example.org" to your domain name
+  server_name example.org;
+
+  # SSL
+  # Uncomment and change the paths to setup
+  # your SSL key/cert. See https://cipherli.st/
+  # for more information
+  #ssl_certificate       /path/to/ssl.cert;
+  #ssl_certificate_key   /path/to/ssl.key;
+
+  # Logs
+  # Uncomment and change the paths to setup
+  # logging
+  #access_log /path/to/access.log;
+  #error_log  /path/to/error.log;
+
+  # Root
+  # Change the path below to where you installed
+  # GNU social
+  root /path/to/gnusocial/root;
+
+  # Index
+  index index.php;
+
+  # PHP
+  location ~ \.php {
+    fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
+    # Remove the "fastcgi_pass" line above and uncomment
+    # the one below to use TCP sockets instead of Unix sockets
+    #fastcgi_pass 127.0.0.1:9000;
+    fastcgi_index index.php;
+    include fastcgi.conf;
+  }
+
+  # Location
+  location / {
+    try_files $uri $uri/ @gnusocial;
+  }
+
+  # Fancy URLs
+  location @gnusocial {
+    rewrite ^(.*)$ /index.php?p=$1 last;
+  }
+}
+
diff --git a/plugins/ChooseTheme/ChooseThemePlugin.php b/plugins/ChooseTheme/ChooseThemePlugin.php
new file mode 100644 (file)
index 0000000..b54e3d0
--- /dev/null
@@ -0,0 +1,74 @@
+<?php
+/**
+ * ChooseTheme - GNU social plugin enabling user to select a preferred theme
+ * Copyright (C) 2015, kollektivet0x242.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author   Knut Erik Hollund <knut.erik@unlike.no>
+ * @copyright 2015 kollektivet0x242. http://www.kollektivet0x242.no
+ *
+ * @license  GNU Affero General Public License http://www.gnu.org/licenses/
+ */
+
+class ChooseThemePlugin extends Plugin {
+
+    public function onRouterInitialized(URLMapper $m) {
+        $m->connect('main/choosethemesettings', array('action' => 'choosethemesettings'));
+    }
+
+    public function onPluginVersion(array &$versions) {
+               
+        $versions[] = array('name' => 'ChooseTheme',
+                            'version' => '0.1',
+                            'author' => 'Knut Erik "abjectio" Hollund',
+                            'homepage' => 'https://gitlab.com/kollektivet0x242/gsp-choosetheme',
+                            'rawdescription' =>
+                            // TRANS: Plugin description.
+                            _m('Allowing user to select the preferred theme.'));
+        return true;
+    }
+    
+    /**
+     * Menu item for ChooseTheme
+     *
+     * @param Action $action action being executed
+     *
+     * @return boolean hook return
+     */
+    function onEndAccountSettingsNav(Action $action) {
+        $action_name = $action->getActionName();
+
+        $action->menuItem(common_local_url('choosethemesettings'),
+                          // TRANS: Poll plugin menu item on user settings page.
+                          _m('MENU', 'Theme'),
+                          // TRANS: Poll plugin tooltip for user settings menu item.
+                          _m('Choose Theme'),
+                          $action_name === 'themesettings');
+
+        return true;
+    }
+
+
+    function onStartShowStylesheets(Action $action) {
+
+               //get the theme and set the current config for site and theme.
+               if($action->getScoped() instanceof Profile) {
+                       $site_theme = common_config('site','theme');
+                       $user_theme = $action->getScoped()->getPref('chosen_theme', 'theme', $site_theme);
+                       common_config_set('site', 'theme', $user_theme);
+               }               
+               return true;
+       }
+}
diff --git a/plugins/ChooseTheme/README.md b/plugins/ChooseTheme/README.md
new file mode 100644 (file)
index 0000000..2e0a761
--- /dev/null
@@ -0,0 +1,13 @@
+### Choose theme
+A simple plugin for [GNU social software](http://gnu.io/social/). 
+The plugin enables the user to select their own theme, independently on site setting and other users.
+
+#### Enable plugin
+- Include this code in your GNU social instance. 
+- Edit your `config.php` to include `addPlugin("ChooseTheme");`
+
+#### How-to
+- Choose settings from the GNU social menu. Choose 'Theme' on left menu.
+- Select a theme and press 'Save'.
+
+
diff --git a/plugins/ChooseTheme/actions/choosethemesettings.php b/plugins/ChooseTheme/actions/choosethemesettings.php
new file mode 100644 (file)
index 0000000..97ef722
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+/**
+ * ChooseTheme - GNU social plugin enabling user to select preferred theme
+ * Copyright (C) 2015, kollektivet0x242.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author   Knut Erik Hollund <knut.erik@unlike.no>
+ * @copyright 2015 kollektivet0x242. http://www.kollektivet0x242.no
+ *
+ * @license  GNU Affero General Public License http://www.gnu.org/licenses/
+ */
+
+if (!defined('STATUSNET') && !defined('GNUSOCIAL')) {
+    exit(1);
+}
+
+class ChooseThemeSettingsAction extends SettingsAction {
+       
+
+    /**
+     * Title of the page
+     * @return string Page title
+     */
+    function title() {
+        // TRANS: Page title.
+        return _m('Choose theme settings');
+    }
+
+    /**
+     * Instructions for use
+     * @return string Instructions for use
+     */
+    function getInstructions() {
+        // TRANS: Page instructions.
+        return _m('Choose theme');
+    }
+
+    /**
+     * Show the form for ChooseTheme
+     * @return void
+     */
+    function showContent() {
+
+       $site_theme = common_config('site','theme');
+       $prefs = $this->scoped->getPref('chosen_theme', 'theme',$site_theme);
+        if ($prefs === null) {
+            common_debug('No chosen theme found in database for user.');
+        }
+       
+       //Get a list of available themes on instance
+       $available_themes = Theme::listAvailable();             
+       $chosenone = array_search($prefs,$available_themes,true);
+        $form = new ChooseThemeForm($this, $chosenone);
+        $form->show();
+    }
+
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     * @return void
+     */
+    function handlePost() {
+               
+       //Get a list of available themes on instance
+       $available_themes = Theme::listAvailable();
+       $chosen_theme = $available_themes[(int)$this->arg('dwct','0')];
+               
+        $this->success = true;
+        $this->msg = _m('Settings saved.');
+
+       $this->success = $this->scoped->setPref('chosen_theme', 'theme', $chosen_theme);
+        // TRANS: Confirmation shown when user profile settings are saved.        
+       if(!$this->success) $this->msg = _('No valid theme chosen.');
+        $this->showForm(_($this->msg), $this->success);
+    }
+}
+
+
+class ChooseThemeForm extends Form {
+
+    protected $prefs = null;
+    
+
+    function __construct($out, $prefs) {
+        parent::__construct($out);
+
+        if ($prefs!=null) {
+                       $this->prefs = $prefs;
+       } else {
+                       $prefs = common_config('site','theme');
+       }
+       
+}
+
+    /**
+     * Visible or invisible data elements
+     *
+     * Display the form fields that make up the data of the form.
+     * Sub-classes should overload this to show their data.
+     * @return void
+     */
+
+    function formData() {
+
+       //Get a list of available themes on instance
+       $available_themes = Theme::listAvailable();
+               
+       //Remove theme 'licenses' from selectable themes.
+       //The 'licenses' theme is not an actual theme and
+       //will just mess-up the gui.
+       $key = array_search('licenses',$available_themes);
+       if($key!=false){
+               unset($available_themes[$key]);
+       }               
+               
+        $this->elementStart('fieldset');
+        $this->elementStart('ul', 'form_data');
+        $this->elementStart('li');
+        $this->dropdown('dwct',_m('Themes'),$available_themes,_m('Select a theme'),false, $this->prefs);
+        $this->elementEnd('li');
+        $this->elementEnd('ul');
+        $this->elementEnd('fieldset');
+      
+    }
+
+    /**
+     * Buttons for form actions
+     *
+     * Submit and cancel buttons (or whatever)
+     * Sub-classes should overload this to show their own buttons.
+     * @return void
+     */
+
+    function formActions()
+    {
+        $this->submit('submit', _('Save'));
+    }
+
+    /**
+     * ID of the form
+     *
+     * Should be unique on the page. Sub-classes should overload this
+     * to show their own IDs.
+     * @return int ID of the form
+     */
+
+    function id() {
+        return 'form_choosetheme_prefs';
+    }
+
+    /**
+     * Action of the form.
+     *
+     * URL to post to. Should be overloaded by subclasses to give
+     * somewhere to post to.
+     * @return string URL to post to
+     */
+
+    function action() {        
+        return common_local_url('choosethemesettings');
+    }
+
+    /**
+     * Class of the form. May include space-separated list of multiple classes.
+     *
+     * @return string the form's class
+     */
+
+    function formClass() {
+        return 'form_settings';
+    }
+}
diff --git a/plugins/ChooseTheme/locale/ChooseTheme.pot b/plugins/ChooseTheme/locale/ChooseTheme.pot
new file mode 100644 (file)
index 0000000..df6c0ca
--- /dev/null
@@ -0,0 +1,62 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the GNU social package.
+# FIRST AUTHOR abjectio@kollektivet0x242.no, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Choose Theme\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-06-10 22:00+0100\n"
+"PO-Revision-Date: 2015-06-10 22:01+0100\n"
+"Last-Translator: Knut Erik Hollund <knut.erik@unlike.no>\n"
+"Language-Team: kollektivet0x242.no <abjectio@kollektivet0x242.no>\n"
+"Language: en\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.4\n"
+"X-Poedit-Basepath: ./actions\n"
+"X-Poedit-KeywordsList: _m\n"
+"X-Poedit-SearchPath-0: ./actions\n"
+"X-Poedit-SearchPath-1: .\n"
+
+#: actions/choosethemesettings.php:38
+msgid "Choose theme settings"
+msgstr ""
+
+#: actions/choosethemesettings.php:47
+msgid "Choose theme"
+msgstr ""
+
+#: actions/choosethemesettings.php:83
+msgid "Settings saved."
+msgstr ""
+
+#: actions/choosethemesettings.php:87
+msgid "No valid theme chosen."
+msgstr ""
+
+#: actions/choosethemesettings.php:134
+msgid "Themes"
+msgstr ""
+
+#: actions/choosethemesettings.php:134
+msgid "Select a theme"
+msgstr ""
+
+#: actions/choosethemesettings.php:151
+msgid "Save"
+msgstr ""
+
+#: ChooseThemePlugin.php:39
+msgid "Allowing user to select the preferred theme."
+msgstr ""
+
+#: ChooseThemePlugin.php:55
+msgid "MENU"
+msgstr ""
+
+#: ChooseThemePlugin.php:57
+msgid "Choose Theme"
+msgstr ""
diff --git a/plugins/ChooseTheme/locale/nb/LC_MESSAGES/ChooseTheme.po b/plugins/ChooseTheme/locale/nb/LC_MESSAGES/ChooseTheme.po
new file mode 100644 (file)
index 0000000..206a477
--- /dev/null
@@ -0,0 +1,62 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the GNU social package.
+# FIRST AUTHOR abjectio@kollektivet0x242.no, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Choose Theme\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-06-10 22:00+0100\n"
+"PO-Revision-Date: 2015-06-10 22:04+0100\n"
+"Last-Translator: Knut Erik Hollund <knut.erik@unlike.no>\n"
+"Language-Team: kollektivet0x242.no <abjectio@kollektivet0x242.no>\n"
+"Language: nb\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Poedit 1.5.4\n"
+"X-Poedit-Basepath: ./actions\n"
+"X-Poedit-KeywordsList: _m\n"
+"X-Poedit-SearchPath-0: ./actions\n"
+"X-Poedit-SearchPath-1: .\n"
+
+#: actions/choosethemesettings.php:38
+msgid "Choose theme settings"
+msgstr "Innstillinger"
+
+#: actions/choosethemesettings.php:47
+msgid "Choose theme"
+msgstr "Velg tema"
+
+#: actions/choosethemesettings.php:83
+msgid "Settings saved."
+msgstr "Innstillinger lagret."
+
+#: actions/choosethemesettings.php:87
+msgid "No valid theme chosen."
+msgstr "Ingen gyldige tema er valgt."
+
+#: actions/choosethemesettings.php:134
+msgid "Themes"
+msgstr "Temaer"
+
+#: actions/choosethemesettings.php:134
+msgid "Select a theme"
+msgstr "Velg tema"
+
+#: actions/choosethemesettings.php:151
+msgid "Save"
+msgstr "Lagre"
+
+#: ChooseThemePlugin.php:39
+msgid "Allowing user to select the preferred theme."
+msgstr "Lar brukeren velge sitt foretrukne tema."
+
+#: ChooseThemePlugin.php:55
+msgid "MENU"
+msgstr "Tema"
+
+#: ChooseThemePlugin.php:57
+msgid "Choose Theme"
+msgstr "Velg tema"