From 34b954122a534ed7e5d18f7e8ab27f0da6fbd2c0 Mon Sep 17 00:00:00 2001
From: sgiehl <stefan@piwik.org>
Date: Sat, 31 Oct 2015 21:44:11 +0100
Subject: [PATCH] move list of socials to other repo and convert format to yml

---
 core/Common.php                               |  26 ---
 plugins/Referrers/API.php                     |  18 +-
 plugins/Referrers/Social.php                  | 182 ++++++++++++++++++
 plugins/Referrers/Tasks.php                   |  17 +-
 plugins/Referrers/functions.php               |  84 --------
 .../Referrers/tests/Unit/ReferrersTest.php    |  76 --------
 plugins/Referrers/tests/Unit/SocialTest.php   | 100 ++++++++++
 7 files changed, 306 insertions(+), 197 deletions(-)
 create mode 100644 plugins/Referrers/Social.php
 create mode 100644 plugins/Referrers/tests/Unit/SocialTest.php

diff --git a/core/Common.php b/core/Common.php
index 6bb4298e93..95d333db9b 100644
--- a/core/Common.php
+++ b/core/Common.php
@@ -815,32 +815,6 @@ class Common
         return $dataProvider->getLanguageToCountryList();
     }
 
-    /**
-     * Returns list of social networks by URL
-     *
-     * @see core/DataFiles/Socials.php
-     *
-     * @return array  Array of ( URL => Social Network Name )
-     */
-    public static function getSocialUrls()
-    {
-        $cacheId = 'Common.getSocialUrls';
-        $cache = Cache::getTransientCache();
-        $socialUrls = $cache->fetch($cacheId);
-
-        if (empty($socialUrls)) {
-            require_once PIWIK_INCLUDE_PATH . '/core/DataFiles/Socials.php';
-
-            $socialUrls = $GLOBALS['Piwik_socialUrl'];
-
-            Piwik::postEvent('Referrer.addSocialUrls', array(&$socialUrls));
-
-            $cache->save($cacheId, $socialUrls);
-        }
-
-        return $socialUrls;
-    }
-
     /**
      * Returns list of provider names
      *
diff --git a/plugins/Referrers/API.php b/plugins/Referrers/API.php
index d1c08ac20c..efda586585 100644
--- a/plugins/Referrers/API.php
+++ b/plugins/Referrers/API.php
@@ -309,9 +309,9 @@ class API extends \Piwik\Plugin\API
     {
         $dataTable = Archive::createDataTableFromArchive(Archiver::WEBSITES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, false);
 
-        $dataTable->filter('ColumnCallbackDeleteRow', array('label', function ($url) { return !isSocialUrl($url); }));
-        $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'url', __NAMESPACE__ . '\getSocialMainUrl'));
-        $dataTable->filter('GroupBy', array('label', __NAMESPACE__ . '\getSocialNetworkFromDomain'));
+        $dataTable->filter('ColumnCallbackDeleteRow', array('label', function ($url) { return !Social::getInstance()->isSocialUrl($url); }));
+        $dataTable->filter('ColumnCallbackAddMetadata', array('label', 'url', function ($url) { return Social::getInstance()->getMainUrl($url); }));
+        $dataTable->filter('GroupBy', array('label', function ($url) { return Social::getInstance()->getSocialNetworkFromDomain($url); }));
 
         $this->setSocialIdSubtables($dataTable);
         $this->removeSubtableMetadata($dataTable);
@@ -320,7 +320,7 @@ class API extends \Piwik\Plugin\API
             $this->buildExpandedTableForFlattenGetSocials($idSite, $period, $date, $segment, $expanded, $dataTable);
         }
 
-        $dataTable->queueFilter('MetadataCallbackAddMetadata', array('url', 'logo', __NAMESPACE__ . '\getSocialsLogoFromUrl'));
+        $dataTable->queueFilter('MetadataCallbackAddMetadata', array('url', 'logo', function ($url) { return Social::getInstance()->getLogoFromUrl($url); }));
 
         return $dataTable;
     }
@@ -344,7 +344,7 @@ class API extends \Piwik\Plugin\API
         $dataTable = $this->getDataTable(Archiver::WEBSITES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded = true);
 
         // get the social network domain referred to by $idSubtable
-        $socialNetworks = Common::getSocialUrls();
+        $socialNetworks = Social::getInstance()->getSocialDefinitions();
 
         $social = false;
         if ($idSubtable !== false) {
@@ -362,7 +362,7 @@ class API extends \Piwik\Plugin\API
         $dataTable->filter(
             'ColumnCallbackDeleteRow',
             array('label',
-                  function ($url) use ($social) { return !isSocialUrl($url, $social); }
+                  function ($url) use ($social) { return !Social::getInstance()->isSocialUrl($url, $social); }
             )
         );
 
@@ -443,7 +443,7 @@ class API extends \Piwik\Plugin\API
                 $socialName = $row->getColumn('label');
 
                 $i = 1; // start at one because idSubtable=0 is equivalent to idSubtable=false
-                foreach (Common::getSocialUrls() as $name) {
+                foreach (Social::getInstance()->getSocialDefinitions() as $name) {
                     if ($name == $socialName) {
                         $row->setNonLoadedSubtableId($i);
                         break;
@@ -491,7 +491,7 @@ class API extends \Piwik\Plugin\API
     {
         $urlsTable = Archive::createDataTableFromArchive(Archiver::WEBSITES_RECORD_NAME, $idSite, $period, $date, $segment, $expanded, $flat = true);
         $urlsTable->filter('ColumnCallbackDeleteRow', array('label', function ($url) {
-            return !isSocialUrl($url);
+            return !Social::getInstance()->isSocialUrl($url);
         }));
         $urlsTable = $urlsTable->mergeSubtables();
 
@@ -504,7 +504,7 @@ class API extends \Piwik\Plugin\API
             $rows = $urlsTable->getRows();
             foreach ($rows as $id => $urlsTableRow) {
                 $url = $urlsTableRow->getColumn('label');
-                if (isSocialUrl($url, $social)) {
+                if (Social::getInstance()->isSocialUrl($url, $social)) {
                     $newTable->addRow($urlsTableRow);
                     $urlsTable->deleteRow($id);
                 }
diff --git a/plugins/Referrers/Social.php b/plugins/Referrers/Social.php
new file mode 100644
index 0000000000..123f31cd32
--- /dev/null
+++ b/plugins/Referrers/Social.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\Referrers;
+use Piwik\Cache;
+use Piwik\Common;
+use Piwik\Option;
+use Piwik\Piwik;
+use Piwik\Singleton;
+use Piwik\UrlHelper;
+
+/**
+ * Contains methods to access search engine definition data.
+ */
+class Social extends Singleton
+{
+    const OPTION_STORAGE_NAME = 'SocialDefinitions';
+
+    /** @var string location of definition file (relative to PIWIK_INCLUDE_PATH) */
+    const DEFINITION_FILE = '/vendor/piwik/searchengine-and-social-definitions/Socials.yml';
+
+    protected $definitionList = null;
+
+    /**
+     * Returns list of search engines by URL
+     *
+     * @return array  Array of ( URL => array( searchEngineName, keywordParameter, path, charset ) )
+     */
+    public function getSocialDefinitions()
+    {
+        $cache = Cache::getEagerCache();
+        $cacheId = 'Social-' . self::OPTION_STORAGE_NAME;
+
+        if ($cache->contains($cacheId)) {
+            $list = $cache->fetch($cacheId);
+        } else {
+            $list = $this->loadSocialDefinitions();
+            $cache->save($cacheId, $list);
+        }
+
+        return $list;
+    }
+
+    private function loadSocialDefinitions()
+    {
+        if ($this->definitionList === null) {
+            // Read first from the auto-updated list in database
+            $list = Option::get(self::OPTION_STORAGE_NAME);
+
+            if ($list) {
+                $this->definitionList = unserialize($list);
+            } else {
+                // Fallback to reading the bundled list
+                $yml = file_get_contents(PIWIK_INCLUDE_PATH . self::DEFINITION_FILE);
+                $this->definitionList = $this->loadYmlData($yml);
+                Option::set(self::OPTION_STORAGE_NAME, serialize($this->definitionList));
+
+            }
+        }
+
+        Piwik::postEvent('Referrer.addSocialUrls', array(&$this->definitionList));
+
+        return $this->definitionList;
+    }
+
+    /**
+     * Parses the given YML string and caches the resulting definitions
+     *
+     * @param string $yml
+     * @return array
+     */
+    public function loadYmlData($yml)
+    {
+        $searchEngines = \Spyc::YAMLLoadString($yml);
+
+        $this->definitionList = $this->transformData($searchEngines);
+
+        return $this->definitionList;
+    }
+
+    protected function transformData($socials)
+    {
+        $urlToName = array();
+        foreach ($socials as $name => $urls) {
+            foreach ($urls as $url) {
+                $urlToName[$url] = $name;
+            }
+        }
+        return $urlToName;
+    }
+
+    /**
+     * Returns true if a URL belongs to a social network, false if otherwise.
+     *
+     * @param string $url The URL to check.
+     * @param string|bool $socialName The social network's name to check for, or false to check
+     *                                 for any.
+     * @return bool
+     */
+    public function isSocialUrl($url, $socialName = false)
+    {
+        foreach ($this->getSocialDefinitions() as $domain => $name) {
+
+            if (preg_match('/(^|[\.\/])'.$domain.'([\.\/]|$)/', $url) && ($socialName === false || $name == $socialName)) {
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+    /**
+     * Get's social network name from URL.
+     *
+     * @param string $url
+     * @return string
+     */
+    public function getSocialNetworkFromDomain($url)
+    {
+        foreach ($this->getSocialDefinitions() as $domain => $name) {
+
+            if (preg_match('/(^|[\.\/])'.$domain.'([\.\/]|$)/', $url)) {
+
+                return $name;
+            }
+        }
+
+        return Piwik::translate('General_Unknown');
+    }
+
+    /**
+     * Returns the main url of the social network the given url matches
+     *
+     * @param string  $url
+     *
+     * @return string
+     */
+    public function getMainUrl($url)
+    {
+        $social  = $this->getSocialNetworkFromDomain($url);
+        foreach ($this->getSocialDefinitions() as $domain => $name) {
+
+            if ($name == $social) {
+
+                return $domain;
+            }
+        }
+        return $url;
+    }
+
+
+    /**
+     * Return social network logo path by URL
+     *
+     * @param string $domain
+     * @return string path
+     * @see plugins/Referrers/images/socials/
+     */
+    public function getLogoFromUrl($domain)
+    {
+        $social = Social::getInstance()->getSocialNetworkFromDomain($domain);
+        $socialNetworks = Social::getInstance()->getSocialDefinitions();
+
+        $filePattern = 'plugins/Referrers/images/socials/%s.png';
+
+        $socialDomains = array_keys($socialNetworks, $social);
+        foreach ($socialDomains as $domain) {
+            if (file_exists(PIWIK_INCLUDE_PATH . '/' . sprintf($filePattern, $domain))) {
+                return sprintf($filePattern, $domain);
+            }
+        }
+
+        return sprintf($filePattern, 'xx');
+    }
+}
diff --git a/plugins/Referrers/Tasks.php b/plugins/Referrers/Tasks.php
index 7481dbdca3..f22699632f 100644
--- a/plugins/Referrers/Tasks.php
+++ b/plugins/Referrers/Tasks.php
@@ -17,11 +17,11 @@ class Tasks extends \Piwik\Plugin\Tasks
     public function schedule()
     {
         $this->weekly('updateSearchEngines');
-        #$this->weekly('updateSocials');
+        $this->weekly('updateSocials');
     }
 
     /**
-     * Update the search engine and social definitions
+     * Update the search engine definitions
      *
      * @see https://github.com/piwik/searchengine-and-social-definitions
      */
@@ -32,4 +32,17 @@ class Tasks extends \Piwik\Plugin\Tasks
         $searchEngines = SearchEngine::getInstance()->loadYmlData($list);
         Option::set(SearchEngine::OPTION_STORAGE_NAME, serialize($searchEngines));
     }
+
+    /**
+     * Update the social definitions
+     *
+     * @see https://github.com/piwik/searchengine-and-social-definitions
+     */
+    public function updateSocials()
+    {
+        $url = 'https://raw.githubusercontent.com/piwik/searchengine-and-social-definitions/master/Socials.yml';
+        $list = Http::sendHttpRequest($url, 30);
+        $searchEngines = SearchEngine::getInstance()->loadYmlData($list);
+        Option::set(SearchEngine::OPTION_STORAGE_NAME, serialize($searchEngines));
+    }
 }
\ No newline at end of file
diff --git a/plugins/Referrers/functions.php b/plugins/Referrers/functions.php
index 2a39f8d1d4..bce573be7e 100644
--- a/plugins/Referrers/functions.php
+++ b/plugins/Referrers/functions.php
@@ -27,89 +27,6 @@ function getPathFromUrl($url)
     return $path;
 }
 
-/**
- * Returns the main url of the social network the given url matches
- *
- * @param string  $url
- *
- * @return string
- */
-function getSocialMainUrl($url)
-{
-    $social  = getSocialNetworkFromDomain($url);
-    foreach (Common::getSocialUrls() as $domain => $name) {
-
-        if ($name == $social) {
-
-            return $domain;
-        }
-    }
-    return $url;
-}
-
-/**
- * Get's social network name from URL.
- *
- * @param string $url
- * @return string
- */
-function getSocialNetworkFromDomain($url)
-{
-    foreach (Common::getSocialUrls() as $domain => $name) {
-
-        if (preg_match('/(^|[\.\/])'.$domain.'([\.\/]|$)/', $url)) {
-
-            return $name;
-        }
-    }
-
-    return Piwik::translate('General_Unknown');
-}
-
-/**
- * Returns true if a URL belongs to a social network, false if otherwise.
- *
- * @param string $url The URL to check.
- * @param string|bool $socialName The social network's name to check for, or false to check
- *                                 for any.
- * @return bool
- */
-function isSocialUrl($url, $socialName = false)
-{
-    foreach (Common::getSocialUrls() as $domain => $name) {
-
-        if (preg_match('/(^|[\.\/])'.$domain.'([\.\/]|$)/', $url) && ($socialName === false || $name == $socialName)) {
-
-            return true;
-        }
-    }
-
-    return false;
-}
-
-/**
- * Return social network logo path by URL
- *
- * @param string $domain
- * @return string path
- * @see plugins/Referrers/images/socials/
- */
-function getSocialsLogoFromUrl($domain)
-{
-    $social = getSocialNetworkFromDomain($domain);
-    $socialNetworks = Common::getSocialUrls();
-
-    $filePattern = 'plugins/Referrers/images/socials/%s.png';
-
-    foreach ($socialNetworks as $domainKey => $name) {
-        if ($social == $socialNetworks[$domainKey] && file_exists(PIWIK_INCLUDE_PATH . '/' . sprintf($filePattern, $domainKey))) {
-            return sprintf($filePattern, $domainKey);
-        }
-    }
-
-    return sprintf($filePattern, 'xx');
-}
-
 /**
  * Return search engine URL by name
  *
@@ -223,7 +140,6 @@ function getSearchEngineUrlFromKeywordAndUrl($keyword, $url)
  */
 function getReferrerTypeLabel($label)
 {
-    $indexTranslation = '';
     switch ($label) {
         case Common::REFERRER_TYPE_DIRECT_ENTRY:
             $indexTranslation = 'Referrers_DirectEntry';
diff --git a/plugins/Referrers/tests/Unit/ReferrersTest.php b/plugins/Referrers/tests/Unit/ReferrersTest.php
index 22e7dbe216..abd4214895 100644
--- a/plugins/Referrers/tests/Unit/ReferrersTest.php
+++ b/plugins/Referrers/tests/Unit/ReferrersTest.php
@@ -155,82 +155,6 @@ class ReferrersTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expected, \Piwik\Plugins\Referrers\getSearchEngineUrlFromUrlAndKeyword($url, $keyword));
     }
 
-    /**
-     * Dataprovider for getSocialNetworkFromDomainTestData
-     */
-    public function getSocialNetworkFromDomainTestData()
-    {
-        return array(
-            array('http://www.facebook.com', 'Facebook'),
-            array('http://www.facebook.com/piwik', 'Facebook'),
-            array('http://m.facebook.com', 'Facebook'),
-            array('https://m.facebook.com', 'Facebook'),
-            array('m.facebook.com', 'Facebook'),
-            array('http://lastfm.com.tr', 'Last.fm'),
-            array('http://t.co/test', 'Twitter'),
-            array('http://xxt.co/test', \Piwik\Piwik::translate('General_Unknown')),
-            array('asdfasdfadsf.com', \Piwik\Piwik::translate('General_Unknown')),
-            array('http://xwayn.com', \Piwik\Piwik::translate('General_Unknown')),
-            array('http://live.com/test', \Piwik\Piwik::translate('General_Unknown')),
-        );
-    }
-
-    /**
-     * @group Plugins
-     *
-     * @dataProvider getSocialNetworkFromDomainTestData
-     */
-    public function testGetSocialNetworkFromDomain($url, $expected)
-    {
-        include PIWIK_INCLUDE_PATH . '/core/DataFiles/Socials.php';
-        $this->assertEquals($expected, \Piwik\Plugins\Referrers\getSocialNetworkFromDomain($url));
-    }
-
-    public function getSocialsLogoFromUrlTestData()
-    {
-        return array(
-            array('http://www.facebook.com', 'facebook.com.png'),
-            array('www.facebook.com', 'facebook.com.png',),
-            array('http://lastfm.com.tr', 'last.fm.png'),
-            array('http://asdfasdf.org/test', 'xx.png'),
-            array('http://www.google.com', 'xx.png'),
-        );
-    }
-
-    /**
-     * @group Plugins
-     *
-     * @dataProvider getSocialsLogoFromUrlTestData
-     */
-    public function testGetSocialsLogoFromUrl($url, $expected)
-    {
-        include PIWIK_INCLUDE_PATH . '/core/DataFiles/Socials.php';
-        $this->assertContains($expected, \Piwik\Plugins\Referrers\getSocialsLogoFromUrl($url));
-    }
-
-    public function isSocialUrlTestData()
-    {
-        return array(
-            array('http://www.facebook.com', 'Facebook', true),
-            array('http://www.facebook.com', 'Twitter', false),
-            array('http://m.facebook.com', false, true),
-            array('http://lastfm.com.tr', 'Last.fm', true),
-            array('http://asdfasdf.org/test', false, false),
-            array('http://asdfasdf.com/test', 'Facebook', false),
-        );
-    }
-
-    /**
-     * @group Plugins
-     *
-     * @dataProvider isSocialUrlTestData
-     */
-    public function testIsSocialUrl($url, $assumedSocial, $expected)
-    {
-        include PIWIK_INCLUDE_PATH . '/core/DataFiles/Socials.php';
-        $this->assertEquals($expected, \Piwik\Plugins\Referrers\isSocialUrl($url, $assumedSocial));
-    }
-
     public function removeUrlProtocolTestData()
     {
         return array(
diff --git a/plugins/Referrers/tests/Unit/SocialTest.php b/plugins/Referrers/tests/Unit/SocialTest.php
new file mode 100644
index 0000000000..bc277b314e
--- /dev/null
+++ b/plugins/Referrers/tests/Unit/SocialTest.php
@@ -0,0 +1,100 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+namespace Piwik\Plugins\Referrers\tests;
+
+use Piwik\Plugins\Referrers\SearchEngine;
+use Piwik\Plugins\Referrers\Social;
+use Spyc;
+
+/**
+ * @group Social
+ * @group Plugins
+ */
+class SocialTest extends \PHPUnit_Framework_TestCase
+{
+    public static function setUpBeforeClass()
+    {
+        // inject definitions to avoid database usage
+        $yml = file_get_contents(PIWIK_INCLUDE_PATH . Social::DEFINITION_FILE);
+        Social::getInstance()->loadYmlData($yml);
+
+        parent::setUpBeforeClass();
+    }
+
+
+    public function isSocialUrlTestData()
+    {
+        return array(
+            array('http://www.facebook.com', 'Facebook', true),
+            array('http://www.facebook.com', 'Twitter', false),
+            array('http://m.facebook.com', false, true),
+            array('http://lastfm.com.tr', 'Last.fm', true),
+            array('http://asdfasdf.org/test', false, false),
+            array('http://asdfasdf.com/test', 'Facebook', false),
+        );
+    }
+
+    /**
+     * @dataProvider isSocialUrlTestData
+     */
+    public function testIsSocialUrl($url, $assumedSocial, $expected)
+    {
+        $this->assertEquals($expected, Social::getInstance()->isSocialUrl($url, $assumedSocial));
+    }
+
+
+    /**
+     * Dataprovider for getSocialNetworkFromDomainTestData
+     */
+    public function getSocialNetworkFromDomainTestData()
+    {
+        return array(
+            array('http://www.facebook.com', 'Facebook'),
+            array('http://www.facebook.com/piwik', 'Facebook'),
+            array('http://m.facebook.com', 'Facebook'),
+            array('https://m.facebook.com', 'Facebook'),
+            array('m.facebook.com', 'Facebook'),
+            array('http://lastfm.com.tr', 'Last.fm'),
+            array('http://t.co/test', 'Twitter'),
+            array('http://xxt.co/test', \Piwik\Piwik::translate('General_Unknown')),
+            array('asdfasdfadsf.com', \Piwik\Piwik::translate('General_Unknown')),
+            array('http://xwayn.com', \Piwik\Piwik::translate('General_Unknown')),
+            array('http://live.com/test', \Piwik\Piwik::translate('General_Unknown')),
+        );
+    }
+
+    /**
+     * @dataProvider getSocialNetworkFromDomainTestData
+     */
+    public function testGetSocialNetworkFromDomain($url, $expected)
+    {
+        $this->assertEquals($expected, Social::getInstance()->getSocialNetworkFromDomain($url));
+    }
+
+    public function getLogoFromUrlTestData()
+    {
+        return array(
+            array('http://www.facebook.com', 'facebook.com.png'),
+            array('www.facebook.com', 'facebook.com.png',),
+            array('http://lastfm.com.tr', 'last.fm.png'),
+            array('http://asdfasdf.org/test', 'xx.png'),
+            array('http://www.google.com', 'xx.png'),
+        );
+    }
+
+    /**
+     * @group Plugins
+     *
+     * @dataProvider getLogoFromUrlTestData
+     */
+    public function testGetLogoFromUrl($url, $expected)
+    {
+        $this->assertContains($expected, Social::getInstance()->getLogoFromUrl($url));
+    }
+}
\ No newline at end of file
-- 
GitLab