add icons for Character groups
This commit is contained in:
commit
2d9a41a5fe
3461 changed files with 594457 additions and 0 deletions
432
www/analytics/plugins/MobileMessaging/API.php
Normal file
432
www/analytics/plugins/MobileMessaging/API.php
Normal file
|
|
@ -0,0 +1,432 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\MobileMessaging;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Option;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\MobileMessaging\SMSProvider;
|
||||
|
||||
/**
|
||||
* The MobileMessaging API lets you manage and access all the MobileMessaging plugin features including :
|
||||
* - manage SMS API credential
|
||||
* - activate phone numbers
|
||||
* - check remaining credits
|
||||
* - send SMS
|
||||
* @method static \Piwik\Plugins\MobileMessaging\API getInstance()
|
||||
*/
|
||||
class API extends \Piwik\Plugin\API
|
||||
{
|
||||
const VERIFICATION_CODE_LENGTH = 5;
|
||||
const SMS_FROM = 'Piwik';
|
||||
|
||||
/**
|
||||
* @param string $provider
|
||||
* @return SMSProvider
|
||||
*/
|
||||
static private function getSMSProviderInstance($provider)
|
||||
{
|
||||
return SMSProvider::factory($provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* determine if SMS API credential are available for the current user
|
||||
*
|
||||
* @return bool true if SMS API credential are available for the current user
|
||||
*/
|
||||
public function areSMSAPICredentialProvided()
|
||||
{
|
||||
Piwik::checkUserHasSomeViewAccess();
|
||||
|
||||
$credential = $this->getSMSAPICredential();
|
||||
return isset($credential[MobileMessaging::API_KEY_OPTION]);
|
||||
}
|
||||
|
||||
private function getSMSAPICredential()
|
||||
{
|
||||
$settings = $this->getCredentialManagerSettings();
|
||||
return array(
|
||||
MobileMessaging::PROVIDER_OPTION =>
|
||||
isset($settings[MobileMessaging::PROVIDER_OPTION]) ? $settings[MobileMessaging::PROVIDER_OPTION] : null,
|
||||
MobileMessaging::API_KEY_OPTION =>
|
||||
isset($settings[MobileMessaging::API_KEY_OPTION]) ? $settings[MobileMessaging::API_KEY_OPTION] : null,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* return the SMS API Provider for the current user
|
||||
*
|
||||
* @return string SMS API Provider
|
||||
*/
|
||||
public function getSMSProvider()
|
||||
{
|
||||
$this->checkCredentialManagementRights();
|
||||
$credential = $this->getSMSAPICredential();
|
||||
return $credential[MobileMessaging::PROVIDER_OPTION];
|
||||
}
|
||||
|
||||
/**
|
||||
* set the SMS API credential
|
||||
*
|
||||
* @param string $provider SMS API provider
|
||||
* @param string $apiKey API Key
|
||||
*
|
||||
* @return bool true if SMS API credential were validated and saved, false otherwise
|
||||
*/
|
||||
public function setSMSAPICredential($provider, $apiKey)
|
||||
{
|
||||
$this->checkCredentialManagementRights();
|
||||
|
||||
$smsProviderInstance = self::getSMSProviderInstance($provider);
|
||||
$smsProviderInstance->verifyCredential($apiKey);
|
||||
|
||||
$settings = $this->getCredentialManagerSettings();
|
||||
|
||||
$settings[MobileMessaging::PROVIDER_OPTION] = $provider;
|
||||
$settings[MobileMessaging::API_KEY_OPTION] = $apiKey;
|
||||
|
||||
$this->setCredentialManagerSettings($settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* add phone number
|
||||
*
|
||||
* @param string $phoneNumber
|
||||
*
|
||||
* @return bool true
|
||||
*/
|
||||
public function addPhoneNumber($phoneNumber)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$phoneNumber = self::sanitizePhoneNumber($phoneNumber);
|
||||
|
||||
$verificationCode = "";
|
||||
for ($i = 0; $i < self::VERIFICATION_CODE_LENGTH; $i++) {
|
||||
$verificationCode .= mt_rand(0, 9);
|
||||
}
|
||||
|
||||
$smsText = Piwik::translate(
|
||||
'MobileMessaging_VerificationText',
|
||||
array(
|
||||
$verificationCode,
|
||||
Piwik::translate('General_Settings'),
|
||||
Piwik::translate('MobileMessaging_SettingsMenu')
|
||||
)
|
||||
);
|
||||
|
||||
$this->sendSMS($smsText, $phoneNumber, self::SMS_FROM);
|
||||
|
||||
$phoneNumbers = $this->retrievePhoneNumbers();
|
||||
$phoneNumbers[$phoneNumber] = $verificationCode;
|
||||
$this->savePhoneNumbers($phoneNumbers);
|
||||
|
||||
$this->increaseCount(MobileMessaging::PHONE_NUMBER_VALIDATION_REQUEST_COUNT_OPTION, $phoneNumber);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* sanitize phone number
|
||||
*
|
||||
* @ignore
|
||||
* @param string $phoneNumber
|
||||
* @return string sanitized phone number
|
||||
*/
|
||||
public static function sanitizePhoneNumber($phoneNumber)
|
||||
{
|
||||
return str_replace(' ', '', $phoneNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* send a SMS
|
||||
*
|
||||
* @param string $content
|
||||
* @param string $phoneNumber
|
||||
* @param string $from
|
||||
* @return bool true
|
||||
* @ignore
|
||||
*/
|
||||
public function sendSMS($content, $phoneNumber, $from)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$credential = $this->getSMSAPICredential();
|
||||
$SMSProvider = self::getSMSProviderInstance($credential[MobileMessaging::PROVIDER_OPTION]);
|
||||
$SMSProvider->sendSMS(
|
||||
$credential[MobileMessaging::API_KEY_OPTION],
|
||||
$content,
|
||||
$phoneNumber,
|
||||
$from
|
||||
);
|
||||
|
||||
$this->increaseCount(MobileMessaging::SMS_SENT_COUNT_OPTION, $phoneNumber);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get remaining credit
|
||||
*
|
||||
* @return string remaining credit
|
||||
*/
|
||||
public function getCreditLeft()
|
||||
{
|
||||
$this->checkCredentialManagementRights();
|
||||
|
||||
$credential = $this->getSMSAPICredential();
|
||||
$SMSProvider = self::getSMSProviderInstance($credential[MobileMessaging::PROVIDER_OPTION]);
|
||||
return $SMSProvider->getCreditLeft(
|
||||
$credential[MobileMessaging::API_KEY_OPTION]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove phone number
|
||||
*
|
||||
* @param string $phoneNumber
|
||||
*
|
||||
* @return bool true
|
||||
*/
|
||||
public function removePhoneNumber($phoneNumber)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$phoneNumbers = $this->retrievePhoneNumbers();
|
||||
unset($phoneNumbers[$phoneNumber]);
|
||||
$this->savePhoneNumbers($phoneNumbers);
|
||||
|
||||
/**
|
||||
* Triggered after a phone number has been deleted. This event should be used to clean up any data that is
|
||||
* related to the now deleted phone number. The ScheduledReports plugin, for example, uses this event to remove
|
||||
* the phone number from all reports to make sure no text message will be sent to this phone number.
|
||||
*
|
||||
* **Example**
|
||||
*
|
||||
* public function deletePhoneNumber($phoneNumber)
|
||||
* {
|
||||
* $this->unsubscribePhoneNumberFromScheduledReport($phoneNumber);
|
||||
* }
|
||||
*
|
||||
* @param string $phoneNumber The phone number that was just deleted.
|
||||
*/
|
||||
Piwik::postEvent('MobileMessaging.deletePhoneNumber', array($phoneNumber));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function retrievePhoneNumbers()
|
||||
{
|
||||
$settings = $this->getCurrentUserSettings();
|
||||
|
||||
$phoneNumbers = array();
|
||||
if (isset($settings[MobileMessaging::PHONE_NUMBERS_OPTION])) {
|
||||
$phoneNumbers = $settings[MobileMessaging::PHONE_NUMBERS_OPTION];
|
||||
}
|
||||
|
||||
return $phoneNumbers;
|
||||
}
|
||||
|
||||
private function savePhoneNumbers($phoneNumbers)
|
||||
{
|
||||
$settings = $this->getCurrentUserSettings();
|
||||
|
||||
$settings[MobileMessaging::PHONE_NUMBERS_OPTION] = $phoneNumbers;
|
||||
|
||||
$this->setCurrentUserSettings($settings);
|
||||
}
|
||||
|
||||
private function increaseCount($option, $phoneNumber)
|
||||
{
|
||||
$settings = $this->getCurrentUserSettings();
|
||||
|
||||
$counts = array();
|
||||
if (isset($settings[$option])) {
|
||||
$counts = $settings[$option];
|
||||
}
|
||||
|
||||
$countToUpdate = 0;
|
||||
if (isset($counts[$phoneNumber])) {
|
||||
$countToUpdate = $counts[$phoneNumber];
|
||||
}
|
||||
|
||||
$counts[$phoneNumber] = $countToUpdate + 1;
|
||||
|
||||
$settings[$option] = $counts;
|
||||
|
||||
$this->setCurrentUserSettings($settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* validate phone number
|
||||
*
|
||||
* @param string $phoneNumber
|
||||
* @param string $verificationCode
|
||||
*
|
||||
* @return bool true if validation code is correct, false otherwise
|
||||
*/
|
||||
public function validatePhoneNumber($phoneNumber, $verificationCode)
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$phoneNumbers = $this->retrievePhoneNumbers();
|
||||
|
||||
if (isset($phoneNumbers[$phoneNumber])) {
|
||||
if ($verificationCode == $phoneNumbers[$phoneNumber]) {
|
||||
|
||||
$phoneNumbers[$phoneNumber] = null;
|
||||
$this->savePhoneNumbers($phoneNumbers);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* get phone number list
|
||||
*
|
||||
* @return array $phoneNumber => $isValidated
|
||||
* @ignore
|
||||
*/
|
||||
public function getPhoneNumbers()
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$rawPhoneNumbers = $this->retrievePhoneNumbers();
|
||||
|
||||
$phoneNumbers = array();
|
||||
foreach ($rawPhoneNumbers as $phoneNumber => $verificationCode) {
|
||||
$phoneNumbers[$phoneNumber] = self::isActivated($verificationCode);
|
||||
}
|
||||
|
||||
return $phoneNumbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* get activated phone number list
|
||||
*
|
||||
* @return array $phoneNumber
|
||||
* @ignore
|
||||
*/
|
||||
public function getActivatedPhoneNumbers()
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$phoneNumbers = $this->retrievePhoneNumbers();
|
||||
|
||||
$activatedPhoneNumbers = array();
|
||||
foreach ($phoneNumbers as $phoneNumber => $verificationCode) {
|
||||
if (self::isActivated($verificationCode)) {
|
||||
$activatedPhoneNumbers[] = $phoneNumber;
|
||||
}
|
||||
}
|
||||
|
||||
return $activatedPhoneNumbers;
|
||||
}
|
||||
|
||||
private static function isActivated($verificationCode)
|
||||
{
|
||||
return $verificationCode === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete the SMS API credential
|
||||
*
|
||||
* @return bool true
|
||||
*/
|
||||
public function deleteSMSAPICredential()
|
||||
{
|
||||
$this->checkCredentialManagementRights();
|
||||
|
||||
$settings = $this->getCredentialManagerSettings();
|
||||
|
||||
$settings[MobileMessaging::API_KEY_OPTION] = null;
|
||||
|
||||
$this->setCredentialManagerSettings($settings);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function checkCredentialManagementRights()
|
||||
{
|
||||
$this->getDelegatedManagement() ? Piwik::checkUserIsNotAnonymous() : Piwik::checkUserHasSuperUserAccess();
|
||||
}
|
||||
|
||||
private function setUserSettings($user, $settings)
|
||||
{
|
||||
Option::set(
|
||||
$user . MobileMessaging::USER_SETTINGS_POSTFIX_OPTION,
|
||||
Common::json_encode($settings)
|
||||
);
|
||||
}
|
||||
|
||||
private function setCurrentUserSettings($settings)
|
||||
{
|
||||
$this->setUserSettings(Piwik::getCurrentUserLogin(), $settings);
|
||||
}
|
||||
|
||||
private function setCredentialManagerSettings($settings)
|
||||
{
|
||||
$this->setUserSettings($this->getCredentialManagerLogin(), $settings);
|
||||
}
|
||||
|
||||
private function getCredentialManagerLogin()
|
||||
{
|
||||
return $this->getDelegatedManagement() ? Piwik::getCurrentUserLogin() : '';
|
||||
}
|
||||
|
||||
private function getUserSettings($user)
|
||||
{
|
||||
$optionIndex = $user . MobileMessaging::USER_SETTINGS_POSTFIX_OPTION;
|
||||
$userSettings = Option::get($optionIndex);
|
||||
|
||||
if (empty($userSettings)) {
|
||||
$userSettings = array();
|
||||
} else {
|
||||
$userSettings = Common::json_decode($userSettings, true);
|
||||
}
|
||||
|
||||
return $userSettings;
|
||||
}
|
||||
|
||||
private function getCredentialManagerSettings()
|
||||
{
|
||||
return $this->getUserSettings($this->getCredentialManagerLogin());
|
||||
}
|
||||
|
||||
private function getCurrentUserSettings()
|
||||
{
|
||||
return $this->getUserSettings(Piwik::getCurrentUserLogin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify if normal users can manage their own SMS API credential
|
||||
*
|
||||
* @param bool $delegatedManagement false if SMS API credential only manageable by super admin, true otherwise
|
||||
*/
|
||||
public function setDelegatedManagement($delegatedManagement)
|
||||
{
|
||||
Piwik::checkUserHasSuperUserAccess();
|
||||
Option::set(MobileMessaging::DELEGATED_MANAGEMENT_OPTION, $delegatedManagement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if normal users can manage their own SMS API credential
|
||||
*
|
||||
* @return bool false if SMS API credential only manageable by super admin, true otherwise
|
||||
*/
|
||||
public function getDelegatedManagement()
|
||||
{
|
||||
Piwik::checkUserHasSomeViewAccess();
|
||||
return Option::get(MobileMessaging::DELEGATED_MANAGEMENT_OPTION) == 'true';
|
||||
}
|
||||
}
|
||||
19
www/analytics/plugins/MobileMessaging/APIException.php
Normal file
19
www/analytics/plugins/MobileMessaging/APIException.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\MobileMessaging;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
*/
|
||||
class APIException extends Exception
|
||||
{
|
||||
|
||||
}
|
||||
78
www/analytics/plugins/MobileMessaging/Controller.php
Normal file
78
www/analytics/plugins/MobileMessaging/Controller.php
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\MobileMessaging;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\IP;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\LanguagesManager\LanguagesManager;
|
||||
use Piwik\Plugins\MobileMessaging\SMSProvider;
|
||||
use Piwik\View;
|
||||
|
||||
require_once PIWIK_INCLUDE_PATH . '/plugins/UserCountry/functions.php';
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Controller extends \Piwik\Plugin\ControllerAdmin
|
||||
{
|
||||
/*
|
||||
* Mobile Messaging Settings tab :
|
||||
* - set delegated management
|
||||
* - provide & validate SMS API credential
|
||||
* - add & activate phone numbers
|
||||
* - check remaining credits
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
Piwik::checkUserIsNotAnonymous();
|
||||
|
||||
$view = new View('@MobileMessaging/index');
|
||||
|
||||
$view->isSuperUser = Piwik::hasUserSuperUserAccess();
|
||||
|
||||
$mobileMessagingAPI = API::getInstance();
|
||||
$view->delegatedManagement = $mobileMessagingAPI->getDelegatedManagement();
|
||||
$view->credentialSupplied = $mobileMessagingAPI->areSMSAPICredentialProvided();
|
||||
$view->accountManagedByCurrentUser = $view->isSuperUser || $view->delegatedManagement;
|
||||
$view->strHelpAddPhone = Piwik::translate('MobileMessaging_Settings_PhoneNumbers_HelpAdd', array(Piwik::translate('General_Settings'), Piwik::translate('MobileMessaging_SettingsMenu')));
|
||||
if ($view->credentialSupplied && $view->accountManagedByCurrentUser) {
|
||||
$view->provider = $mobileMessagingAPI->getSMSProvider();
|
||||
$view->creditLeft = $mobileMessagingAPI->getCreditLeft();
|
||||
}
|
||||
|
||||
$view->smsProviders = SMSProvider::$availableSMSProviders;
|
||||
|
||||
// construct the list of countries from the lang files
|
||||
$countries = array();
|
||||
foreach (Common::getCountriesList() as $countryCode => $continentCode) {
|
||||
if (isset(CountryCallingCodes::$countryCallingCodes[$countryCode])) {
|
||||
$countries[$countryCode] =
|
||||
array(
|
||||
'countryName' => \Piwik\Plugins\UserCountry\countryTranslate($countryCode),
|
||||
'countryCallingCode' => CountryCallingCodes::$countryCallingCodes[$countryCode],
|
||||
);
|
||||
}
|
||||
}
|
||||
$view->countries = $countries;
|
||||
|
||||
$view->defaultCountry = Common::getCountry(
|
||||
LanguagesManager::getLanguageCodeForCurrentUser(),
|
||||
true,
|
||||
IP::getIpFromHeader()
|
||||
);
|
||||
|
||||
$view->phoneNumbers = $mobileMessagingAPI->getPhoneNumbers();
|
||||
|
||||
$this->setBasicVariablesView($view);
|
||||
|
||||
return $view->render();
|
||||
}
|
||||
}
|
||||
270
www/analytics/plugins/MobileMessaging/CountryCallingCodes.php
Normal file
270
www/analytics/plugins/MobileMessaging/CountryCallingCodes.php
Normal file
|
|
@ -0,0 +1,270 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\MobileMessaging;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class CountryCallingCodes
|
||||
{
|
||||
// list taken from core/DataFiles/Countries.php
|
||||
public static $countryCallingCodes = array(
|
||||
'ad' => '376',
|
||||
'ae' => '971',
|
||||
'af' => '93',
|
||||
'ag' => '1268', // @wikipedia original value: 1 268
|
||||
'ai' => '1264', // @wikipedia original value: 1 264
|
||||
'al' => '355',
|
||||
'am' => '374',
|
||||
'ao' => '244',
|
||||
// 'aq' => 'MISSING CODE', // @wikipedia In Antarctica dialing is dependent on the parent country of each base
|
||||
'ar' => '54',
|
||||
'as' => '1684', // @wikipedia original value: 1 684
|
||||
'at' => '43',
|
||||
'au' => '61',
|
||||
'aw' => '297',
|
||||
'ax' => '358',
|
||||
'az' => '994',
|
||||
'ba' => '387',
|
||||
'bb' => '1246', // @wikipedia original value: 1 246
|
||||
'bd' => '880',
|
||||
'be' => '32',
|
||||
'bf' => '226',
|
||||
'bg' => '359',
|
||||
'bh' => '973',
|
||||
'bi' => '257',
|
||||
'bj' => '229',
|
||||
'bl' => '590',
|
||||
'bm' => '1441', // @wikipedia original value: 1 441
|
||||
'bn' => '673',
|
||||
'bo' => '591',
|
||||
'bq' => '5997', // @wikipedia original value: 599 7
|
||||
'br' => '55',
|
||||
'bs' => '1242', // @wikipedia original value: 1 242
|
||||
'bt' => '975',
|
||||
// 'bv' => 'MISSING CODE',
|
||||
'bw' => '267',
|
||||
'by' => '375',
|
||||
'bz' => '501',
|
||||
'ca' => '1',
|
||||
'cc' => '61',
|
||||
'cd' => '243',
|
||||
'cf' => '236',
|
||||
'cg' => '242',
|
||||
'ch' => '41',
|
||||
'ci' => '225',
|
||||
'ck' => '682',
|
||||
'cl' => '56',
|
||||
'cm' => '237',
|
||||
'cn' => '86',
|
||||
'co' => '57',
|
||||
'cr' => '506',
|
||||
'cu' => '53',
|
||||
'cv' => '238',
|
||||
'cw' => '5999', // @wikipedia original value: 599 9
|
||||
'cx' => '61',
|
||||
'cy' => '357',
|
||||
'cz' => '420',
|
||||
'de' => '49',
|
||||
'dj' => '253',
|
||||
'dk' => '45',
|
||||
'dm' => '1767', // @wikipedia original value: 1 767
|
||||
// 'do' => 'MISSING CODE', // @wikipedia original values: 1 809, 1 829, 1 849
|
||||
'dz' => '213',
|
||||
'ec' => '593',
|
||||
'ee' => '372',
|
||||
'eg' => '20',
|
||||
'eh' => '212',
|
||||
'er' => '291',
|
||||
'es' => '34',
|
||||
'et' => '251',
|
||||
'fi' => '358',
|
||||
'fj' => '679',
|
||||
'fk' => '500',
|
||||
'fm' => '691',
|
||||
'fo' => '298',
|
||||
'fr' => '33',
|
||||
'ga' => '241',
|
||||
'gb' => '44',
|
||||
'gd' => '1473', // @wikipedia original value: 1 473
|
||||
'ge' => '995',
|
||||
'gf' => '594',
|
||||
'gg' => '44',
|
||||
'gh' => '233',
|
||||
'gi' => '350',
|
||||
'gl' => '299',
|
||||
'gm' => '220',
|
||||
'gn' => '224',
|
||||
'gp' => '590',
|
||||
'gq' => '240',
|
||||
'gr' => '30',
|
||||
'gs' => '500',
|
||||
'gt' => '502',
|
||||
'gu' => '1671', // @wikipedia original value: 1 671
|
||||
'gw' => '245',
|
||||
'gy' => '592',
|
||||
'hk' => '852',
|
||||
// 'hm' => 'MISSING CODE',
|
||||
'hn' => '504',
|
||||
'hr' => '385',
|
||||
'ht' => '509',
|
||||
'hu' => '36',
|
||||
'id' => '62',
|
||||
'ie' => '353',
|
||||
'il' => '972',
|
||||
'im' => '44',
|
||||
'in' => '91',
|
||||
'io' => '246',
|
||||
'iq' => '964',
|
||||
'ir' => '98',
|
||||
'is' => '354',
|
||||
'it' => '39',
|
||||
'je' => '44',
|
||||
'jm' => '1876', // @wikipedia original value: 1 876
|
||||
'jo' => '962',
|
||||
'jp' => '81',
|
||||
'ke' => '254',
|
||||
'kg' => '996',
|
||||
'kh' => '855',
|
||||
'ki' => '686',
|
||||
'km' => '269',
|
||||
'kn' => '1869', // @wikipedia original value: 1 869
|
||||
'kp' => '850',
|
||||
'kr' => '82',
|
||||
'kw' => '965',
|
||||
'ky' => '1345', // @wikipedia original value: 1 345
|
||||
// 'kz' => 'MISSING CODE', // @wikipedia original values: 7 6, 7 7
|
||||
'la' => '856',
|
||||
'lb' => '961',
|
||||
'lc' => '1758', // @wikipedia original value: 1 758
|
||||
'li' => '423',
|
||||
'lk' => '94',
|
||||
'lr' => '231',
|
||||
'ls' => '266',
|
||||
'lt' => '370',
|
||||
'lu' => '352',
|
||||
'lv' => '371',
|
||||
'ly' => '218',
|
||||
'ma' => '212',
|
||||
'mc' => '377',
|
||||
'md' => '373',
|
||||
'me' => '382',
|
||||
'mf' => '590',
|
||||
'mg' => '261',
|
||||
'mh' => '692',
|
||||
'mk' => '389',
|
||||
'ml' => '223',
|
||||
'mm' => '95',
|
||||
'mn' => '976',
|
||||
'mo' => '853',
|
||||
'mp' => '1670', // @wikipedia original value: 1 670
|
||||
'mq' => '596',
|
||||
'mr' => '222',
|
||||
'ms' => '1664', // @wikipedia original value: 1 664
|
||||
'mt' => '356',
|
||||
'mu' => '230',
|
||||
'mv' => '960',
|
||||
'mw' => '265',
|
||||
'mx' => '52',
|
||||
'my' => '60',
|
||||
'mz' => '258',
|
||||
'na' => '264',
|
||||
'nc' => '687',
|
||||
'ne' => '227',
|
||||
'nf' => '672',
|
||||
'ng' => '234',
|
||||
'ni' => '505',
|
||||
'nl' => '31',
|
||||
'no' => '47',
|
||||
'np' => '977',
|
||||
'nr' => '674',
|
||||
'nu' => '683',
|
||||
'nz' => '64',
|
||||
'om' => '968',
|
||||
'pa' => '507',
|
||||
'pe' => '51',
|
||||
'pf' => '689',
|
||||
'pg' => '675',
|
||||
'ph' => '63',
|
||||
'pk' => '92',
|
||||
'pl' => '48',
|
||||
'pm' => '508',
|
||||
'pn' => '672',
|
||||
// 'pr' => 'MISSING CODE', // @wikipedia original values: 1 787, 1 939
|
||||
'ps' => '970',
|
||||
'pt' => '351',
|
||||
'pw' => '680',
|
||||
'py' => '595',
|
||||
'qa' => '974',
|
||||
're' => '262',
|
||||
'ro' => '40',
|
||||
'rs' => '381',
|
||||
'ru' => '7',
|
||||
'rw' => '250',
|
||||
'sa' => '966',
|
||||
'sb' => '677',
|
||||
'sc' => '248',
|
||||
'sd' => '249',
|
||||
'se' => '46',
|
||||
'sg' => '65',
|
||||
'sh' => '290',
|
||||
'si' => '386',
|
||||
'sj' => '47',
|
||||
'sk' => '421',
|
||||
'sl' => '232',
|
||||
'sm' => '378',
|
||||
'sn' => '221',
|
||||
'so' => '252',
|
||||
'sr' => '597',
|
||||
'ss' => '211',
|
||||
'st' => '239',
|
||||
'sv' => '503',
|
||||
'sx' => '1721', //@wikipedia original value: 1 721
|
||||
'sy' => '963',
|
||||
'sz' => '268',
|
||||
'tc' => '1649', // @wikipedia original value: 1 649
|
||||
'td' => '235',
|
||||
// 'tf' => 'MISSING CODE',
|
||||
'tg' => '228',
|
||||
'th' => '66',
|
||||
// 'ti' => 'MISSING CODE',
|
||||
'tj' => '992',
|
||||
'tk' => '690',
|
||||
'tl' => '670',
|
||||
'tm' => '993',
|
||||
'tn' => '216',
|
||||
'to' => '676',
|
||||
'tr' => '90',
|
||||
'tt' => '1868', // @wikipedia original value: 1 868
|
||||
'tv' => '688',
|
||||
'tw' => '886',
|
||||
'tz' => '255',
|
||||
'ua' => '380',
|
||||
'ug' => '256',
|
||||
// 'um' => 'MISSING CODE',
|
||||
'us' => '1',
|
||||
'uy' => '598',
|
||||
'uz' => '998',
|
||||
// 'va' => 'MISSING CODE', // @wikipedia original values: 39 066, assigned 379
|
||||
'vc' => '1784', // @wikipedia original value: 1 784
|
||||
've' => '58',
|
||||
'vg' => '1284', // @wikipedia original value: 1 284
|
||||
'vi' => '1340', // @wikipedia original value: 1 340
|
||||
'vn' => '84',
|
||||
'vu' => '678',
|
||||
'wf' => '681',
|
||||
'ws' => '685',
|
||||
'ye' => '967',
|
||||
'yt' => '262',
|
||||
'za' => '27',
|
||||
'zm' => '260',
|
||||
'zw' => '263'
|
||||
);
|
||||
}
|
||||
158
www/analytics/plugins/MobileMessaging/GSMCharset.php
Normal file
158
www/analytics/plugins/MobileMessaging/GSMCharset.php
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\MobileMessaging;
|
||||
|
||||
/**
|
||||
* GSM 03.38 Charset
|
||||
*
|
||||
*/
|
||||
class GSMCharset
|
||||
{
|
||||
public static $GSMCharset = array(
|
||||
|
||||
// Standard GSM Characters, weight = 1
|
||||
'@' => 1,
|
||||
'£' => 1,
|
||||
'$' => 1,
|
||||
'¥' => 1,
|
||||
'è' => 1,
|
||||
'é' => 1,
|
||||
'ù' => 1,
|
||||
'ì' => 1,
|
||||
'ò' => 1,
|
||||
'Ç' => 1,
|
||||
'Ø' => 1,
|
||||
'ø' => 1,
|
||||
'Å' => 1,
|
||||
'å' => 1,
|
||||
'∆' => 1,
|
||||
'_' => 1,
|
||||
'Φ' => 1,
|
||||
'Γ' => 1,
|
||||
'Λ' => 1,
|
||||
'Ω' => 1,
|
||||
'Π' => 1,
|
||||
'Ψ' => 1,
|
||||
'Σ' => 1,
|
||||
'Θ' => 1,
|
||||
'Ξ' => 1,
|
||||
'Æ' => 1,
|
||||
'æ' => 1,
|
||||
'ß' => 1,
|
||||
'É' => 1,
|
||||
' ' => 1,
|
||||
'!' => 1,
|
||||
'"' => 1,
|
||||
'#' => 1,
|
||||
'¤' => 1,
|
||||
'%' => 1,
|
||||
'&' => 1,
|
||||
'\'' => 1,
|
||||
'(' => 1,
|
||||
')' => 1,
|
||||
'*' => 1,
|
||||
'+' => 1,
|
||||
',' => 1,
|
||||
'-' => 1,
|
||||
'.' => 1,
|
||||
'/' => 1,
|
||||
'0' => 1,
|
||||
'1' => 1,
|
||||
'2' => 1,
|
||||
'3' => 1,
|
||||
'4' => 1,
|
||||
'5' => 1,
|
||||
'6' => 1,
|
||||
'7' => 1,
|
||||
'8' => 1,
|
||||
'9' => 1,
|
||||
':' => 1,
|
||||
';' => 1,
|
||||
'<' => 1,
|
||||
'=' => 1,
|
||||
'>' => 1,
|
||||
'?' => 1,
|
||||
'¡' => 1,
|
||||
'A' => 1,
|
||||
'B' => 1,
|
||||
'C' => 1,
|
||||
'D' => 1,
|
||||
'E' => 1,
|
||||
'F' => 1,
|
||||
'G' => 1,
|
||||
'H' => 1,
|
||||
'I' => 1,
|
||||
'J' => 1,
|
||||
'K' => 1,
|
||||
'L' => 1,
|
||||
'M' => 1,
|
||||
'N' => 1,
|
||||
'O' => 1,
|
||||
'P' => 1,
|
||||
'Q' => 1,
|
||||
'R' => 1,
|
||||
'S' => 1,
|
||||
'T' => 1,
|
||||
'U' => 1,
|
||||
'V' => 1,
|
||||
'W' => 1,
|
||||
'X' => 1,
|
||||
'Y' => 1,
|
||||
'Z' => 1,
|
||||
'Ä' => 1,
|
||||
'Ö' => 1,
|
||||
'Ñ' => 1,
|
||||
'Ü' => 1,
|
||||
'§' => 1,
|
||||
'¿' => 1,
|
||||
'a' => 1,
|
||||
'b' => 1,
|
||||
'c' => 1,
|
||||
'd' => 1,
|
||||
'e' => 1,
|
||||
'f' => 1,
|
||||
'g' => 1,
|
||||
'h' => 1,
|
||||
'i' => 1,
|
||||
'j' => 1,
|
||||
'k' => 1,
|
||||
'l' => 1,
|
||||
'm' => 1,
|
||||
'n' => 1,
|
||||
'o' => 1,
|
||||
'p' => 1,
|
||||
'q' => 1,
|
||||
'r' => 1,
|
||||
's' => 1,
|
||||
't' => 1,
|
||||
'u' => 1,
|
||||
'v' => 1,
|
||||
'w' => 1,
|
||||
'x' => 1,
|
||||
'y' => 1,
|
||||
'z' => 1,
|
||||
'ä' => 1,
|
||||
'ö' => 1,
|
||||
'ñ' => 1,
|
||||
'ü' => 1,
|
||||
'à' => 1,
|
||||
|
||||
// Extended GSM Characters, weight = 2
|
||||
'^' => 2,
|
||||
'{' => 2,
|
||||
'}' => 2,
|
||||
'\\' => 2,
|
||||
'[' => 2,
|
||||
'~' => 2,
|
||||
']' => 2,
|
||||
'|' => 2,
|
||||
'€' => 2,
|
||||
);
|
||||
}
|
||||
257
www/analytics/plugins/MobileMessaging/MobileMessaging.php
Normal file
257
www/analytics/plugins/MobileMessaging/MobileMessaging.php
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\MobileMessaging;
|
||||
|
||||
use Piwik\Menu\MenuAdmin;
|
||||
use Piwik\Option;
|
||||
use Piwik\Piwik;
|
||||
use Piwik\Plugins\API\API as APIPlugins;
|
||||
use Piwik\Plugins\MobileMessaging\API as APIMobileMessaging;
|
||||
use Piwik\Plugins\MobileMessaging\ReportRenderer\ReportRendererException;
|
||||
use Piwik\Plugins\MobileMessaging\ReportRenderer\Sms;
|
||||
use Piwik\Plugins\ScheduledReports\API as APIScheduledReports;
|
||||
use Piwik\View;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class MobileMessaging extends \Piwik\Plugin
|
||||
{
|
||||
const DELEGATED_MANAGEMENT_OPTION = 'MobileMessaging_DelegatedManagement';
|
||||
const PROVIDER_OPTION = 'Provider';
|
||||
const API_KEY_OPTION = 'APIKey';
|
||||
const PHONE_NUMBERS_OPTION = 'PhoneNumbers';
|
||||
const PHONE_NUMBER_VALIDATION_REQUEST_COUNT_OPTION = 'PhoneNumberValidationRequestCount';
|
||||
const SMS_SENT_COUNT_OPTION = 'SMSSentCount';
|
||||
const DELEGATED_MANAGEMENT_OPTION_DEFAULT = 'false';
|
||||
const USER_SETTINGS_POSTFIX_OPTION = '_MobileMessagingSettings';
|
||||
|
||||
const PHONE_NUMBERS_PARAMETER = 'phoneNumbers';
|
||||
|
||||
const MOBILE_TYPE = 'mobile';
|
||||
const SMS_FORMAT = 'sms';
|
||||
|
||||
static private $availableParameters = array(
|
||||
self::PHONE_NUMBERS_PARAMETER => true,
|
||||
);
|
||||
|
||||
static private $managedReportTypes = array(
|
||||
self::MOBILE_TYPE => 'plugins/MobileMessaging/images/phone.png'
|
||||
);
|
||||
|
||||
static private $managedReportFormats = array(
|
||||
self::SMS_FORMAT => 'plugins/MobileMessaging/images/phone.png'
|
||||
);
|
||||
|
||||
static private $availableReports = array(
|
||||
array(
|
||||
'module' => 'MultiSites',
|
||||
'action' => 'getAll',
|
||||
),
|
||||
array(
|
||||
'module' => 'MultiSites',
|
||||
'action' => 'getOne',
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* @see Piwik\Plugin::getListHooksRegistered
|
||||
*/
|
||||
public function getListHooksRegistered()
|
||||
{
|
||||
return array(
|
||||
'Menu.Admin.addItems' => 'addMenu',
|
||||
'AssetManager.getJavaScriptFiles' => 'getJsFiles',
|
||||
'AssetManager.getStylesheetFiles' => 'getStylesheetFiles',
|
||||
'ScheduledReports.getReportParameters' => 'getReportParameters',
|
||||
'ScheduledReports.validateReportParameters' => 'validateReportParameters',
|
||||
'ScheduledReports.getReportMetadata' => 'getReportMetadata',
|
||||
'ScheduledReports.getReportTypes' => 'getReportTypes',
|
||||
'ScheduledReports.getReportFormats' => 'getReportFormats',
|
||||
'ScheduledReports.getRendererInstance' => 'getRendererInstance',
|
||||
'ScheduledReports.getReportRecipients' => 'getReportRecipients',
|
||||
'ScheduledReports.allowMultipleReports' => 'allowMultipleReports',
|
||||
'ScheduledReports.sendReport' => 'sendReport',
|
||||
'Template.reportParametersScheduledReports' => 'template_reportParametersScheduledReports',
|
||||
);
|
||||
}
|
||||
|
||||
function addMenu()
|
||||
{
|
||||
MenuAdmin::addEntry('MobileMessaging_SettingsMenu',
|
||||
array('module' => 'MobileMessaging', 'action' => 'index'),
|
||||
true,
|
||||
$order = 12
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JavaScript files
|
||||
*/
|
||||
public function getJsFiles(&$jsFiles)
|
||||
{
|
||||
$jsFiles[] = "plugins/MobileMessaging/javascripts/MobileMessagingSettings.js";
|
||||
}
|
||||
|
||||
public function getStylesheetFiles(&$stylesheets)
|
||||
{
|
||||
$stylesheets[] = "plugins/MobileMessaging/stylesheets/MobileMessagingSettings.less";
|
||||
}
|
||||
|
||||
public function validateReportParameters(&$parameters, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
// phone number validation
|
||||
$availablePhoneNumbers = APIMobileMessaging::getInstance()->getActivatedPhoneNumbers();
|
||||
|
||||
$phoneNumbers = $parameters[self::PHONE_NUMBERS_PARAMETER];
|
||||
foreach ($phoneNumbers as $key => $phoneNumber) {
|
||||
//when a wrong phone number is supplied we silently discard it
|
||||
if (!in_array($phoneNumber, $availablePhoneNumbers)) {
|
||||
unset($phoneNumbers[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
// 'unset' seems to transform the array to an associative array
|
||||
$parameters[self::PHONE_NUMBERS_PARAMETER] = array_values($phoneNumbers);
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportMetadata(&$availableReportMetadata, $reportType, $idSite)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
foreach (self::$availableReports as $availableReport) {
|
||||
$reportMetadata = APIPlugins::getInstance()->getMetadata(
|
||||
$idSite,
|
||||
$availableReport['module'],
|
||||
$availableReport['action']
|
||||
);
|
||||
|
||||
if ($reportMetadata != null) {
|
||||
$reportMetadata = reset($reportMetadata);
|
||||
$availableReportMetadata[] = $reportMetadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportTypes(&$reportTypes)
|
||||
{
|
||||
$reportTypes = array_merge($reportTypes, self::$managedReportTypes);
|
||||
}
|
||||
|
||||
public function getReportFormats(&$reportFormats, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$reportFormats = array_merge($reportFormats, self::$managedReportFormats);
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportParameters(&$availableParameters, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$availableParameters = self::$availableParameters;
|
||||
}
|
||||
}
|
||||
|
||||
public function getRendererInstance(&$reportRenderer, $reportType, $outputType, $report)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
if (\Piwik\Plugin\Manager::getInstance()->isPluginActivated('MultiSites')) {
|
||||
$reportRenderer = new Sms();
|
||||
} else {
|
||||
$reportRenderer = new ReportRendererException(
|
||||
Piwik::translate('MobileMessaging_MultiSites_Must_Be_Activated')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function allowMultipleReports(&$allowMultipleReports, $reportType)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$allowMultipleReports = false;
|
||||
}
|
||||
}
|
||||
|
||||
public function getReportRecipients(&$recipients, $reportType, $report)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$recipients = $report['parameters'][self::PHONE_NUMBERS_PARAMETER];
|
||||
}
|
||||
}
|
||||
|
||||
public function sendReport($reportType, $report, $contents, $filename, $prettyDate, $reportSubject, $reportTitle,
|
||||
$additionalFiles)
|
||||
{
|
||||
if (self::manageEvent($reportType)) {
|
||||
$parameters = $report['parameters'];
|
||||
$phoneNumbers = $parameters[self::PHONE_NUMBERS_PARAMETER];
|
||||
|
||||
// 'All Websites' is one character above the limit, use 'Reports' instead
|
||||
if ($reportSubject == Piwik::translate('General_MultiSitesSummary')) {
|
||||
$reportSubject = Piwik::translate('General_Reports');
|
||||
}
|
||||
|
||||
$mobileMessagingAPI = APIMobileMessaging::getInstance();
|
||||
foreach ($phoneNumbers as $phoneNumber) {
|
||||
$mobileMessagingAPI->sendSMS(
|
||||
$contents,
|
||||
$phoneNumber,
|
||||
$reportSubject
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public function template_reportParametersScheduledReports(&$out)
|
||||
{
|
||||
if (Piwik::isUserIsAnonymous()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$view = new View('@MobileMessaging/reportParametersScheduledReports');
|
||||
$view->reportType = self::MOBILE_TYPE;
|
||||
$view->phoneNumbers = APIMobileMessaging::getInstance()->getActivatedPhoneNumbers();
|
||||
$out .= $view->render();
|
||||
}
|
||||
|
||||
private static function manageEvent($reportType)
|
||||
{
|
||||
return in_array($reportType, array_keys(self::$managedReportTypes));
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
$delegatedManagement = Option::get(self::DELEGATED_MANAGEMENT_OPTION);
|
||||
if (empty($delegatedManagement)) {
|
||||
Option::set(self::DELEGATED_MANAGEMENT_OPTION, self::DELEGATED_MANAGEMENT_OPTION_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
function deactivate()
|
||||
{
|
||||
// delete all mobile reports
|
||||
$APIScheduledReports = APIScheduledReports::getInstance();
|
||||
$reports = $APIScheduledReports->getReports();
|
||||
|
||||
foreach ($reports as $report) {
|
||||
if ($report['type'] == MobileMessaging::MOBILE_TYPE) {
|
||||
$APIScheduledReports->deleteReport($report['idreport']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function uninstall()
|
||||
{
|
||||
// currently the UI does not allow to delete a plugin
|
||||
// when it becomes available, all the MobileMessaging settings (API credentials, phone numbers, etc..) should be removed from the option table
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\MobileMessaging\ReportRenderer;
|
||||
|
||||
use Piwik\ReportRenderer;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class ReportRendererException extends ReportRenderer
|
||||
{
|
||||
private $rendering = "";
|
||||
|
||||
function __construct($exception)
|
||||
{
|
||||
$this->rendering = $exception;
|
||||
}
|
||||
|
||||
public function setLocale($locale)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public function sendToDisk($filename)
|
||||
{
|
||||
return ReportRenderer::writeFile(
|
||||
$filename,
|
||||
Sms::SMS_FILE_EXTENSION,
|
||||
$this->rendering
|
||||
);
|
||||
}
|
||||
|
||||
public function sendToBrowserDownload($filename)
|
||||
{
|
||||
ReportRenderer::sendToBrowser(
|
||||
$filename,
|
||||
Sms::SMS_FILE_EXTENSION,
|
||||
Sms::SMS_CONTENT_TYPE,
|
||||
$this->rendering
|
||||
);
|
||||
}
|
||||
|
||||
public function sendToBrowserInline($filename)
|
||||
{
|
||||
ReportRenderer::inlineToBrowser(
|
||||
Sms::SMS_CONTENT_TYPE,
|
||||
$this->rendering
|
||||
);
|
||||
}
|
||||
|
||||
public function getRenderedReport()
|
||||
{
|
||||
return $this->rendering;
|
||||
}
|
||||
|
||||
public function renderFrontPage($reportTitle, $prettyDate, $description, $reportMetadata, $segment)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public function renderReport($processedReport)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
131
www/analytics/plugins/MobileMessaging/ReportRenderer/Sms.php
Normal file
131
www/analytics/plugins/MobileMessaging/ReportRenderer/Sms.php
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\MobileMessaging\ReportRenderer;
|
||||
|
||||
use Piwik\Common;
|
||||
use Piwik\Plugins\MultiSites\API;
|
||||
use Piwik\ReportRenderer;
|
||||
use Piwik\Site;
|
||||
use Piwik\View;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Sms extends ReportRenderer
|
||||
{
|
||||
const FLOAT_REGEXP = '/[-+]?[0-9]*[\.,]?[0-9]+/';
|
||||
const SMS_CONTENT_TYPE = 'text/plain';
|
||||
const SMS_FILE_EXTENSION = 'sms';
|
||||
|
||||
private $rendering = "";
|
||||
|
||||
public function setLocale($locale)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public function sendToDisk($filename)
|
||||
{
|
||||
return ReportRenderer::writeFile($filename, self::SMS_FILE_EXTENSION, $this->rendering);
|
||||
}
|
||||
|
||||
public function sendToBrowserDownload($filename)
|
||||
{
|
||||
ReportRenderer::sendToBrowser($filename, self::SMS_FILE_EXTENSION, self::SMS_CONTENT_TYPE, $this->rendering);
|
||||
}
|
||||
|
||||
public function sendToBrowserInline($filename)
|
||||
{
|
||||
ReportRenderer::inlineToBrowser(self::SMS_CONTENT_TYPE, $this->rendering);
|
||||
}
|
||||
|
||||
public function getRenderedReport()
|
||||
{
|
||||
return $this->rendering;
|
||||
}
|
||||
|
||||
public function renderFrontPage($reportTitle, $prettyDate, $description, $reportMetadata, $segment)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public function renderReport($processedReport)
|
||||
{
|
||||
$isGoalPluginEnabled = Common::isGoalPluginEnabled();
|
||||
$prettyDate = $processedReport['prettyDate'];
|
||||
$reportData = $processedReport['reportData'];
|
||||
|
||||
$evolutionMetrics = array();
|
||||
$multiSitesAPIMetrics = API::getApiMetrics($enhanced = true);
|
||||
foreach ($multiSitesAPIMetrics as $metricSettings) {
|
||||
$evolutionMetrics[] = $metricSettings[API::METRIC_EVOLUTION_COL_NAME_KEY];
|
||||
}
|
||||
|
||||
$floatRegex = self::FLOAT_REGEXP;
|
||||
// no decimal for all metrics to shorten SMS content (keeps the monetary sign for revenue metrics)
|
||||
$reportData->filter(
|
||||
'ColumnCallbackReplace',
|
||||
array(
|
||||
array_merge(array_keys($multiSitesAPIMetrics), $evolutionMetrics),
|
||||
function ($value) use ($floatRegex) {
|
||||
return preg_replace_callback(
|
||||
$floatRegex,
|
||||
function ($matches) {
|
||||
return round($matches[0]);
|
||||
},
|
||||
$value
|
||||
);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
// evolution metrics formatting :
|
||||
// - remove monetary, percentage and white spaces to shorten SMS content
|
||||
// (this is also needed to be able to test $value != 0 and see if there is an evolution at all in SMSReport.twig)
|
||||
// - adds a plus sign
|
||||
$reportData->filter(
|
||||
'ColumnCallbackReplace',
|
||||
array(
|
||||
$evolutionMetrics,
|
||||
function ($value) use ($floatRegex) {
|
||||
$matched = preg_match($floatRegex, $value, $matches);
|
||||
return $matched ? sprintf("%+d", $matches[0]) : $value;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
$dataRows = $reportData->getRows();
|
||||
$reportMetadata = $processedReport['reportMetadata'];
|
||||
$reportRowsMetadata = $reportMetadata->getRows();
|
||||
|
||||
$siteHasECommerce = array();
|
||||
foreach ($reportRowsMetadata as $rowMetadata) {
|
||||
$idSite = $rowMetadata->getColumn('idsite');
|
||||
$siteHasECommerce[$idSite] = Site::isEcommerceEnabledFor($idSite);
|
||||
}
|
||||
|
||||
$view = new View('@MobileMessaging/SMSReport');
|
||||
$view->assign("isGoalPluginEnabled", $isGoalPluginEnabled);
|
||||
$view->assign("reportRows", $dataRows);
|
||||
$view->assign("reportRowsMetadata", $reportRowsMetadata);
|
||||
$view->assign("prettyDate", $prettyDate);
|
||||
$view->assign("siteHasECommerce", $siteHasECommerce);
|
||||
$view->assign("displaySiteName", $processedReport['metadata']['action'] == 'getAll');
|
||||
|
||||
// segment
|
||||
$segment = $processedReport['segment'];
|
||||
$displaySegment = ($segment != null);
|
||||
$view->assign("displaySegment", $displaySegment);
|
||||
if ($displaySegment) {
|
||||
$view->assign("segmentName", $segment['name']);
|
||||
}
|
||||
|
||||
$this->rendering .= $view->render();
|
||||
}
|
||||
}
|
||||
174
www/analytics/plugins/MobileMessaging/SMSProvider.php
Normal file
174
www/analytics/plugins/MobileMessaging/SMSProvider.php
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\MobileMessaging;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Loader;
|
||||
use Piwik\Piwik;
|
||||
|
||||
/**
|
||||
* The SMSProvider abstract class is used as a base class for SMS provider implementations.
|
||||
*
|
||||
*/
|
||||
abstract class SMSProvider
|
||||
{
|
||||
const MAX_GSM_CHARS_IN_ONE_UNIQUE_SMS = 160;
|
||||
const MAX_GSM_CHARS_IN_ONE_CONCATENATED_SMS = 153;
|
||||
const MAX_UCS2_CHARS_IN_ONE_UNIQUE_SMS = 70;
|
||||
const MAX_UCS2_CHARS_IN_ONE_CONCATENATED_SMS = 67;
|
||||
|
||||
static public $availableSMSProviders = array(
|
||||
'Clockwork' => 'You can use <a target="_blank" href="?module=Proxy&action=redirect&url=http://www.clockworksms.com/platforms/piwik/"><img src="plugins/MobileMessaging/images/Clockwork.png"/></a> to send SMS Reports from Piwik.<br/>
|
||||
<ul>
|
||||
<li> First, <a target="_blank" href="?module=Proxy&action=redirect&url=http://www.clockworksms.com/platforms/piwik/">get an API Key from Clockwork</a> (Signup is free!)
|
||||
</li><li> Enter your Clockwork API Key on this page. </li>
|
||||
</ul>
|
||||
<br/><em>About Clockwork: </em><ul>
|
||||
<li>Clockwork gives you fast, reliable high quality worldwide SMS delivery, over 450 networks in every corner of the globe.
|
||||
</li><li>Cost per SMS message is around ~0.08USD (0.06EUR).
|
||||
</li><li>Most countries and networks are supported but we suggest you check the latest position on their coverage map <a target="_blank" href="?module=Proxy&action=redirect&url=http://www.clockworksms.com/sms-coverage/">here</a>.
|
||||
</li>
|
||||
</ul>
|
||||
',
|
||||
);
|
||||
|
||||
/**
|
||||
* Return the SMSProvider associated to the provider name $providerName
|
||||
*
|
||||
* @throws Exception If the provider is unknown
|
||||
* @param string $providerName
|
||||
* @return \Piwik\Plugins\MobileMessaging\SMSProvider
|
||||
*/
|
||||
static public function factory($providerName)
|
||||
{
|
||||
$className = __NAMESPACE__ . '\\SMSProvider\\' . $providerName;
|
||||
|
||||
try {
|
||||
Loader::loadClass($className);
|
||||
return new $className;
|
||||
} catch (Exception $e) {
|
||||
throw new Exception(
|
||||
Piwik::translate(
|
||||
'MobileMessaging_Exception_UnknownProvider',
|
||||
array($providerName, implode(', ', array_keys(self::$availableSMSProviders)))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert whether a given String contains UCS2 characters
|
||||
*
|
||||
* @param string $string
|
||||
* @return bool true if $string contains UCS2 characters
|
||||
*/
|
||||
static public function containsUCS2Characters($string)
|
||||
{
|
||||
$GSMCharsetAsString = implode(array_keys(GSMCharset::$GSMCharset));
|
||||
|
||||
foreach (self::mb_str_split($string) as $char) {
|
||||
if (mb_strpos($GSMCharsetAsString, $char) === false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate $string and append $appendedString at the end if $string can not fit the
|
||||
* the $maximumNumberOfConcatenatedSMS.
|
||||
*
|
||||
* @param string $string String to truncate
|
||||
* @param int $maximumNumberOfConcatenatedSMS
|
||||
* @param string $appendedString
|
||||
* @return string original $string or truncated $string appended with $appendedString
|
||||
*/
|
||||
static public function truncate($string, $maximumNumberOfConcatenatedSMS, $appendedString = 'MobileMessaging_SMS_Content_Too_Long')
|
||||
{
|
||||
$appendedString = Piwik::translate($appendedString);
|
||||
|
||||
$smsContentContainsUCS2Chars = self::containsUCS2Characters($string);
|
||||
$maxCharsAllowed = self::maxCharsAllowed($maximumNumberOfConcatenatedSMS, $smsContentContainsUCS2Chars);
|
||||
$sizeOfSMSContent = self::sizeOfSMSContent($string, $smsContentContainsUCS2Chars);
|
||||
|
||||
if ($sizeOfSMSContent <= $maxCharsAllowed) return $string;
|
||||
|
||||
$smsContentContainsUCS2Chars = $smsContentContainsUCS2Chars || self::containsUCS2Characters($appendedString);
|
||||
$maxCharsAllowed = self::maxCharsAllowed($maximumNumberOfConcatenatedSMS, $smsContentContainsUCS2Chars);
|
||||
$sizeOfSMSContent = self::sizeOfSMSContent($string . $appendedString, $smsContentContainsUCS2Chars);
|
||||
|
||||
$sizeToTruncate = $sizeOfSMSContent - $maxCharsAllowed;
|
||||
|
||||
$subStrToTruncate = '';
|
||||
$subStrSize = 0;
|
||||
$reversedStringChars = array_reverse(self::mb_str_split($string));
|
||||
for ($i = 0; $subStrSize < $sizeToTruncate; $i++) {
|
||||
$subStrToTruncate = $reversedStringChars[$i] . $subStrToTruncate;
|
||||
$subStrSize = self::sizeOfSMSContent($subStrToTruncate, $smsContentContainsUCS2Chars);
|
||||
}
|
||||
|
||||
return preg_replace('/' . preg_quote($subStrToTruncate, '/') . '$/', $appendedString, $string);
|
||||
}
|
||||
|
||||
static private function mb_str_split($string)
|
||||
{
|
||||
return preg_split('//u', $string, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
static private function sizeOfSMSContent($smsContent, $containsUCS2Chars)
|
||||
{
|
||||
if ($containsUCS2Chars) return mb_strlen($smsContent, 'UTF-8');
|
||||
|
||||
$sizeOfSMSContent = 0;
|
||||
foreach (self::mb_str_split($smsContent) as $char) {
|
||||
$sizeOfSMSContent += GSMCharset::$GSMCharset[$char];
|
||||
}
|
||||
return $sizeOfSMSContent;
|
||||
}
|
||||
|
||||
static private function maxCharsAllowed($maximumNumberOfConcatenatedSMS, $containsUCS2Chars)
|
||||
{
|
||||
$maxCharsInOneUniqueSMS = $containsUCS2Chars ? self::MAX_UCS2_CHARS_IN_ONE_UNIQUE_SMS : self::MAX_GSM_CHARS_IN_ONE_UNIQUE_SMS;
|
||||
$maxCharsInOneConcatenatedSMS = $containsUCS2Chars ? self::MAX_UCS2_CHARS_IN_ONE_CONCATENATED_SMS : self::MAX_GSM_CHARS_IN_ONE_CONCATENATED_SMS;
|
||||
|
||||
$uniqueSMS = $maximumNumberOfConcatenatedSMS == 1;
|
||||
|
||||
return $uniqueSMS ?
|
||||
$maxCharsInOneUniqueSMS :
|
||||
$maxCharsInOneConcatenatedSMS * $maximumNumberOfConcatenatedSMS;
|
||||
}
|
||||
|
||||
/**
|
||||
* verify the SMS API credential
|
||||
*
|
||||
* @param string $apiKey API Key
|
||||
* @return bool true if SMS API credential are valid, false otherwise
|
||||
*/
|
||||
abstract public function verifyCredential($apiKey);
|
||||
|
||||
/**
|
||||
* get remaining credits
|
||||
*
|
||||
* @param string $apiKey API Key
|
||||
* @return string remaining credits
|
||||
*/
|
||||
abstract public function getCreditLeft($apiKey);
|
||||
|
||||
/**
|
||||
* send SMS
|
||||
*
|
||||
* @param string $apiKey
|
||||
* @param string $smsText
|
||||
* @param string $phoneNumber
|
||||
* @param string $from
|
||||
* @return bool true
|
||||
*/
|
||||
abstract public function sendSMS($apiKey, $smsText, $phoneNumber, $from);
|
||||
}
|
||||
108
www/analytics/plugins/MobileMessaging/SMSProvider/Clockwork.php
Normal file
108
www/analytics/plugins/MobileMessaging/SMSProvider/Clockwork.php
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
|
||||
namespace Piwik\Plugins\MobileMessaging\SMSProvider;
|
||||
|
||||
use Exception;
|
||||
use Piwik\Http;
|
||||
use Piwik\Plugins\MobileMessaging\APIException;
|
||||
use Piwik\Plugins\MobileMessaging\SMSProvider;
|
||||
|
||||
require_once PIWIK_INCLUDE_PATH . "/plugins/MobileMessaging/APIException.php";
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Clockwork extends SMSProvider
|
||||
{
|
||||
const SOCKET_TIMEOUT = 15;
|
||||
|
||||
const BASE_API_URL = 'https://api.mediaburst.co.uk/http';
|
||||
const CHECK_CREDIT_RESOURCE = '/credit.aspx';
|
||||
const SEND_SMS_RESOURCE = '/send.aspx';
|
||||
|
||||
const ERROR_STRING = 'Error';
|
||||
|
||||
const MAXIMUM_FROM_LENGTH = 11;
|
||||
const MAXIMUM_CONCATENATED_SMS = 3;
|
||||
|
||||
public function verifyCredential($apiKey)
|
||||
{
|
||||
$this->getCreditLeft($apiKey);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sendSMS($apiKey, $smsText, $phoneNumber, $from)
|
||||
{
|
||||
$from = substr($from, 0, self::MAXIMUM_FROM_LENGTH);
|
||||
|
||||
$smsText = self::truncate($smsText, self::MAXIMUM_CONCATENATED_SMS);
|
||||
|
||||
$additionalParameters = array(
|
||||
'To' => str_replace('+', '', $phoneNumber),
|
||||
'Content' => $smsText,
|
||||
'From' => $from,
|
||||
'Long' => 1,
|
||||
'MsgType' => self::containsUCS2Characters($smsText) ? 'UCS2' : 'TEXT',
|
||||
);
|
||||
|
||||
$this->issueApiCall(
|
||||
$apiKey,
|
||||
self::SEND_SMS_RESOURCE,
|
||||
$additionalParameters
|
||||
);
|
||||
}
|
||||
|
||||
private function issueApiCall($apiKey, $resource, $additionalParameters = array())
|
||||
{
|
||||
$accountParameters = array(
|
||||
'Key' => $apiKey,
|
||||
);
|
||||
|
||||
$parameters = array_merge($accountParameters, $additionalParameters);
|
||||
|
||||
$url = self::BASE_API_URL
|
||||
. $resource
|
||||
. '?' . http_build_query($parameters, '', '&');
|
||||
|
||||
$timeout = self::SOCKET_TIMEOUT;
|
||||
|
||||
try {
|
||||
$result = Http::sendHttpRequestBy(
|
||||
Http::getTransportMethod(),
|
||||
$url,
|
||||
$timeout,
|
||||
$userAgent = null,
|
||||
$destinationPath = null,
|
||||
$file = null,
|
||||
$followDepth = 0,
|
||||
$acceptLanguage = false,
|
||||
$acceptInvalidSslCertificate = true
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
$result = self::ERROR_STRING . " " . $e->getMessage();
|
||||
}
|
||||
|
||||
if (strpos($result, self::ERROR_STRING) !== false) {
|
||||
throw new APIException(
|
||||
'Clockwork API returned the following error message : ' . $result
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getCreditLeft($apiKey)
|
||||
{
|
||||
return $this->issueApiCall(
|
||||
$apiKey,
|
||||
self::CHECK_CREDIT_RESOURCE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*
|
||||
*/
|
||||
namespace Piwik\Plugins\MobileMessaging\SMSProvider;
|
||||
|
||||
use Piwik\Plugins\MobileMessaging\SMSProvider;
|
||||
|
||||
/**
|
||||
* Used for testing
|
||||
*
|
||||
*/
|
||||
class StubbedProvider extends SMSProvider
|
||||
{
|
||||
|
||||
public function verifyCredential($apiKey)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sendSMS($apiKey, $smsText, $phoneNumber, $from)
|
||||
{
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public function getCreditLeft($apiKey)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
BIN
www/analytics/plugins/MobileMessaging/images/Clockwork.png
Normal file
BIN
www/analytics/plugins/MobileMessaging/images/Clockwork.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
www/analytics/plugins/MobileMessaging/images/phone.png
Normal file
BIN
www/analytics/plugins/MobileMessaging/images/phone.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 568 B |
|
|
@ -0,0 +1,266 @@
|
|||
/**
|
||||
* Piwik - Open source web analytics
|
||||
*
|
||||
* @link http://piwik.org
|
||||
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
||||
*/
|
||||
|
||||
// TODO when UI stabilized, factorize ajax boiler plate accros MobileMessagingSettings javascript functions
|
||||
var MobileMessagingSettings = MobileMessagingSettings || (function () {
|
||||
|
||||
/************************************************************
|
||||
* Private data
|
||||
************************************************************/
|
||||
var
|
||||
delegatedManagementSelector = 'input[name=delegatedManagement]',
|
||||
apiAccountSubmitSelector = '#apiAccountSubmit',
|
||||
addPhoneNumberSubmitSelector = '#addPhoneNumberSubmit',
|
||||
providersSelector = '#smsProviders',
|
||||
providerDescriptionsSelector = '.providerDescription',
|
||||
apiKeySelector = '#apiKey',
|
||||
countriesSelector = '#countries',
|
||||
countryCallingCodeSelector = '#countryCallingCode',
|
||||
newPhoneNumberSelector = '#newPhoneNumber',
|
||||
suspiciousPhoneNumberSelector = '#suspiciousPhoneNumber',
|
||||
validatePhoneNumberSubmitSelector = '.validatePhoneNumberSubmit',
|
||||
formDescriptionSelector = '.form-description',
|
||||
removePhoneNumberSubmitSelector = '.removePhoneNumberSubmit',
|
||||
verificationCodeSelector = '.verificationCode',
|
||||
phoneNumberSelector = '.phoneNumber',
|
||||
deleteAcountSelector = '#deleteAccount',
|
||||
confirmDeleteAccountSelector = '#confirmDeleteAccount',
|
||||
accountFormSelector = '#accountForm',
|
||||
displayAccountFormSelector = '#displayAccountForm',
|
||||
phoneNumberActivatedSelector = '#phoneNumberActivated',
|
||||
invalidActivationCodeMsgSelector = '#invalidActivationCode',
|
||||
ajaxErrorsSelector = '#ajaxErrorMobileMessagingSettings',
|
||||
invalidVerificationCodeAjaxErrorSelector = '#invalidVerificationCodeAjaxError',
|
||||
ajaxLoadingSelector = '#ajaxLoadingMobileMessagingSettings';
|
||||
|
||||
/************************************************************
|
||||
* Private methods
|
||||
************************************************************/
|
||||
|
||||
function initUIEvents() {
|
||||
|
||||
$(delegatedManagementSelector).change(updateDelegatedManagement);
|
||||
$(apiAccountSubmitSelector).click(updateApiAccount);
|
||||
$(deleteAcountSelector).click(confirmDeleteApiAccount);
|
||||
$(displayAccountFormSelector).click(displayAccountForm);
|
||||
$(addPhoneNumberSubmitSelector).click(addPhoneNumber);
|
||||
$(newPhoneNumberSelector).keyup(updateSuspiciousPhoneNumberMessage);
|
||||
$(validatePhoneNumberSubmitSelector).click(validatePhoneNumber);
|
||||
$(removePhoneNumberSubmitSelector).click(removePhoneNumber);
|
||||
$(countryCallingCodeSelector).keyup(updateCountry);
|
||||
$(countriesSelector).change(updateCountryCallingCode);
|
||||
updateCountryCallingCode();
|
||||
$(providersSelector).change(updateProviderDescription);
|
||||
updateProviderDescription();
|
||||
}
|
||||
|
||||
function updateCountry() {
|
||||
var countryCallingCode = $(countryCallingCodeSelector).val();
|
||||
if (countryCallingCode != null && countryCallingCode != '') {
|
||||
var countryToSelect = $(countriesSelector + ' option[value=' + countryCallingCode + ']');
|
||||
if (countryToSelect.size() > 0) {
|
||||
countryToSelect.attr('selected', 'selected');
|
||||
}
|
||||
else {
|
||||
$(countriesSelector + ' option:selected').removeAttr('selected');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function displayAccountForm() {
|
||||
$(accountFormSelector).show();
|
||||
}
|
||||
|
||||
function validatePhoneNumber(event) {
|
||||
var phoneNumberContainer = $(event.target).parent();
|
||||
var verificationCodeContainer = phoneNumberContainer.find(verificationCodeSelector);
|
||||
var verificationCode = verificationCodeContainer.val();
|
||||
var phoneNumber = phoneNumberContainer.find(phoneNumberSelector).html();
|
||||
|
||||
if (verificationCode != null && verificationCode != '') {
|
||||
var success =
|
||||
function (response) {
|
||||
|
||||
var UI = require('piwik/UI');
|
||||
var notification = new UI.Notification();
|
||||
|
||||
$(phoneNumberActivatedSelector).hide();
|
||||
if (!response.value) {
|
||||
var message = $(invalidActivationCodeMsgSelector).html();
|
||||
notification.show(message, {
|
||||
context: 'error',
|
||||
id: 'MobileMessaging_ValidatePhoneNumber',
|
||||
style: {marginTop: '10px'}
|
||||
});
|
||||
}
|
||||
else {
|
||||
var message = $(phoneNumberActivatedSelector).html();
|
||||
notification.show(message, {
|
||||
context: 'success',
|
||||
id: 'MobileMessaging_ValidatePhoneNumber',
|
||||
style: {marginTop: '10px'}
|
||||
});
|
||||
|
||||
$(verificationCodeContainer).remove();
|
||||
$(phoneNumberContainer).find(validatePhoneNumberSubmitSelector).remove();
|
||||
$(phoneNumberContainer).find(formDescriptionSelector).remove();
|
||||
}
|
||||
|
||||
notification.scrollToNotification();
|
||||
};
|
||||
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
module: 'API',
|
||||
format: 'json',
|
||||
method: 'MobileMessaging.validatePhoneNumber'
|
||||
}, 'GET');
|
||||
ajaxHandler.addParams({phoneNumber: phoneNumber, verificationCode: verificationCode}, 'POST');
|
||||
ajaxHandler.setCallback(success);
|
||||
ajaxHandler.setLoadingElement(ajaxLoadingSelector);
|
||||
ajaxHandler.setErrorElement(invalidVerificationCodeAjaxErrorSelector);
|
||||
ajaxHandler.send(true);
|
||||
}
|
||||
}
|
||||
|
||||
function removePhoneNumber(event) {
|
||||
var phoneNumberContainer = $(event.target).parent();
|
||||
var phoneNumber = phoneNumberContainer.find(phoneNumberSelector).html();
|
||||
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
module: 'API',
|
||||
format: 'json',
|
||||
method: 'MobileMessaging.removePhoneNumber'
|
||||
}, 'GET');
|
||||
ajaxHandler.addParams({phoneNumber: phoneNumber}, 'POST');
|
||||
ajaxHandler.redirectOnSuccess();
|
||||
ajaxHandler.setLoadingElement(ajaxLoadingSelector);
|
||||
ajaxHandler.setErrorElement(ajaxErrorsSelector);
|
||||
ajaxHandler.send(true);
|
||||
}
|
||||
|
||||
function updateSuspiciousPhoneNumberMessage() {
|
||||
var newPhoneNumber = $(newPhoneNumberSelector).val();
|
||||
|
||||
// check if number starts with 0
|
||||
if ($.trim(newPhoneNumber).lastIndexOf('0', 0) === 0) {
|
||||
$(suspiciousPhoneNumberSelector).show();
|
||||
}
|
||||
else {
|
||||
$(suspiciousPhoneNumberSelector).hide();
|
||||
}
|
||||
}
|
||||
|
||||
function addPhoneNumber() {
|
||||
var newPhoneNumber = $(newPhoneNumberSelector).val();
|
||||
var countryCallingCode = $(countryCallingCodeSelector).val();
|
||||
|
||||
var phoneNumber = '+' + countryCallingCode + newPhoneNumber;
|
||||
|
||||
if (newPhoneNumber != null && newPhoneNumber != '') {
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
module: 'API',
|
||||
format: 'json',
|
||||
method: 'MobileMessaging.addPhoneNumber'
|
||||
}, 'GET');
|
||||
ajaxHandler.addParams({phoneNumber: phoneNumber}, 'POST');
|
||||
ajaxHandler.redirectOnSuccess();
|
||||
ajaxHandler.setLoadingElement(ajaxLoadingSelector);
|
||||
ajaxHandler.setErrorElement(ajaxErrorsSelector);
|
||||
ajaxHandler.send(true);
|
||||
}
|
||||
}
|
||||
|
||||
function updateCountryCallingCode() {
|
||||
$(countryCallingCodeSelector).val($(countriesSelector + ' option:selected').val());
|
||||
}
|
||||
|
||||
function updateProviderDescription() {
|
||||
$(providerDescriptionsSelector).hide();
|
||||
$('#' + $(providersSelector + ' option:selected').val() + providerDescriptionsSelector).show();
|
||||
}
|
||||
|
||||
function updateDelegatedManagement() {
|
||||
setDelegatedManagement(getDelegatedManagement());
|
||||
}
|
||||
|
||||
function confirmDeleteApiAccount() {
|
||||
piwikHelper.modalConfirm(confirmDeleteAccountSelector, {yes: deleteApiAccount});
|
||||
}
|
||||
|
||||
function deleteApiAccount() {
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
module: 'API',
|
||||
format: 'json',
|
||||
method: 'MobileMessaging.deleteSMSAPICredential'
|
||||
}, 'GET');
|
||||
ajaxHandler.redirectOnSuccess();
|
||||
ajaxHandler.setLoadingElement(ajaxLoadingSelector);
|
||||
ajaxHandler.setErrorElement(ajaxErrorsSelector);
|
||||
ajaxHandler.send(true);
|
||||
}
|
||||
|
||||
function updateApiAccount() {
|
||||
|
||||
var provider = $(providersSelector + ' option:selected').val();
|
||||
var apiKey = $(apiKeySelector).val();
|
||||
|
||||
if (apiKey != '') {
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
module: 'API',
|
||||
format: 'json',
|
||||
method: 'MobileMessaging.setSMSAPICredential'
|
||||
}, 'GET');
|
||||
ajaxHandler.addParams({provider: provider, apiKey: apiKey}, 'POST');
|
||||
ajaxHandler.redirectOnSuccess();
|
||||
ajaxHandler.setLoadingElement(ajaxLoadingSelector);
|
||||
ajaxHandler.setErrorElement(ajaxErrorsSelector);
|
||||
ajaxHandler.send(true);
|
||||
}
|
||||
}
|
||||
|
||||
function setDelegatedManagement(delegatedManagement) {
|
||||
var ajaxHandler = new ajaxHelper();
|
||||
ajaxHandler.addParams({
|
||||
module: 'API',
|
||||
format: 'json',
|
||||
method: 'MobileMessaging.setDelegatedManagement'
|
||||
}, 'GET');
|
||||
ajaxHandler.addParams({delegatedManagement: delegatedManagement}, 'POST');
|
||||
ajaxHandler.redirectOnSuccess();
|
||||
ajaxHandler.setLoadingElement(ajaxLoadingSelector);
|
||||
ajaxHandler.setErrorElement(ajaxErrorsSelector);
|
||||
ajaxHandler.send(true);
|
||||
}
|
||||
|
||||
function getDelegatedManagement() {
|
||||
return $(delegatedManagementSelector + ':checked').val();
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
* Public data and methods
|
||||
************************************************************/
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* Initialize UI events
|
||||
*/
|
||||
initUIEvents: function () {
|
||||
initUIEvents();
|
||||
}
|
||||
};
|
||||
|
||||
}());
|
||||
|
||||
$(document).ready(function () {
|
||||
MobileMessagingSettings.initUIEvents();
|
||||
});
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#accountForm ul {
|
||||
list-style: circle;
|
||||
margin-left: 17px;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
.providerDescription {
|
||||
border: 2px dashed #C5BDAD;
|
||||
border-radius: 16px 16px 16px 16px;
|
||||
margin-left: 24px;
|
||||
padding: 11px;
|
||||
width: 600px;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
{{ prettyDate }}{% if displaySegment %}, {{ segmentName }}{% endif %}. {% if false %}{% endif %}
|
||||
|
||||
{%- if reportRows is empty -%}
|
||||
{{ 'CoreHome_ThereIsNoDataForThisReport'|translate }}
|
||||
{%- endif -%}
|
||||
|
||||
{%- for rowId, row in reportRows -%}
|
||||
{%- set rowMetrics=row.columns -%}
|
||||
{%- set rowMetadata=reportRowsMetadata[rowId].columns -%}
|
||||
|
||||
{%- if displaySiteName -%}{{ rowMetrics.label|raw }}: {% endif -%}
|
||||
|
||||
{# visits #}
|
||||
{{- rowMetrics.nb_visits }} {{ 'General_ColumnNbVisits'|translate }}
|
||||
{%- if rowMetrics.visits_evolution != 0 %} ({{ rowMetrics.visits_evolution }}%){%- endif -%}
|
||||
|
||||
{%- if rowMetrics.nb_visits != 0 -%}
|
||||
{#- actions -#}
|
||||
, {{ rowMetrics.nb_actions }} {{ 'General_ColumnNbActions'|translate }}
|
||||
{%- if rowMetrics.actions_evolution != 0 %} ({{ rowMetrics.actions_evolution }}%){%- endif -%}
|
||||
|
||||
{%- if isGoalPluginEnabled -%}
|
||||
|
||||
{# goal metrics #}
|
||||
{%- if rowMetrics.nb_conversions != 0 -%}
|
||||
, {{ 'General_ColumnRevenue'|translate }}: {{ rowMetrics.revenue|raw }}
|
||||
{%- if rowMetrics.revenue_evolution != 0 %} ({{ rowMetrics.revenue_evolution }}%){%- endif -%}
|
||||
|
||||
, {{ rowMetrics.nb_conversions }} {{ 'Goals_GoalConversions'|translate }}
|
||||
{%- if rowMetrics.nb_conversions_evolution != 0 %} ({{ rowMetrics.nb_conversions_evolution }}%){%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{# eCommerce metrics #}
|
||||
{%- if siteHasECommerce[rowMetadata.idsite] -%}
|
||||
|
||||
, {{ 'General_ProductRevenue'|translate }}: {{ rowMetrics.ecommerce_revenue|raw }}
|
||||
{%- if rowMetrics.ecommerce_revenue_evolution != 0 %} ({{ rowMetrics.ecommerce_revenue_evolution }}%){%- endif -%}
|
||||
|
||||
, {{ rowMetrics.orders }} {{ 'General_EcommerceOrders'|translate }}
|
||||
{%- if rowMetrics.orders_evolution != 0 %} ({{ rowMetrics.orders_evolution }}%){%- endif -%}
|
||||
{%- endif -%}
|
||||
|
||||
{%- endif -%}
|
||||
|
||||
{%- endif -%}
|
||||
|
||||
{%- if not loop.last -%}. {% endif -%}
|
||||
{%- endfor -%}
|
||||
200
www/analytics/plugins/MobileMessaging/templates/index.twig
Normal file
200
www/analytics/plugins/MobileMessaging/templates/index.twig
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
{% extends 'admin.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{% if accountManagedByCurrentUser %}
|
||||
<h2 piwik-enriched-headline
|
||||
feature-name="{{ 'MobileMessaging_SettingsMenu'|translate }}"
|
||||
>{{ 'MobileMessaging_Settings_SMSAPIAccount'|translate }}</h2>
|
||||
{% if credentialSupplied %}
|
||||
{{ 'MobileMessaging_Settings_CredentialProvided'|translate(provider) }}
|
||||
{{ creditLeft }}
|
||||
<br/>
|
||||
{{ 'MobileMessaging_Settings_UpdateOrDeleteAccount'|translate("<a id='displayAccountForm'>","</a>","<a id='deleteAccount'>","</a>")|raw }}
|
||||
{% else %}
|
||||
{{ 'MobileMessaging_Settings_PleaseSignUp'|translate }}
|
||||
{% endif %}
|
||||
<div id='accountForm' {% if credentialSupplied %}style='display: none;'{% endif %}>
|
||||
<br/>
|
||||
{{ 'MobileMessaging_Settings_SMSProvider'|translate }}
|
||||
<select id='smsProviders'>
|
||||
{% for smsProvider, description in smsProviders %}
|
||||
<option value='{{ smsProvider }}'>
|
||||
{{ smsProvider }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
{{ 'MobileMessaging_Settings_APIKey'|translate }}
|
||||
<input size='25' id='apiKey'/>
|
||||
|
||||
<input type='submit' value='{{ 'General_Save'|translate }}' id='apiAccountSubmit' class='submit'/>
|
||||
|
||||
{% for smsProvider, description in smsProviders %}
|
||||
<div class='providerDescription' id='{{ smsProvider }}'>
|
||||
{{ description|raw }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% import 'ajaxMacros.twig' as ajax %}
|
||||
|
||||
<div style="margin-top:10px">
|
||||
{{ ajax.errorDiv('ajaxErrorMobileMessagingSettings') }}
|
||||
</div>
|
||||
|
||||
<h2>{{ 'MobileMessaging_PhoneNumbers'|translate }}</h2>
|
||||
{% if not credentialSupplied %}
|
||||
{% if accountManagedByCurrentUser %}
|
||||
{{ 'MobileMessaging_Settings_CredentialNotProvided'|translate }}
|
||||
{% else %}
|
||||
{{ 'MobileMessaging_Settings_CredentialNotProvidedByAdmin'|translate }}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ 'MobileMessaging_Settings_PhoneNumbers_Help'|translate }}
|
||||
<br/>
|
||||
<br/>
|
||||
<table style="width:900px;" class="adminTable">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width:480px;">
|
||||
<strong>{{ 'MobileMessaging_Settings_PhoneNumbers_Add'|translate }}</strong>
|
||||
<br/><br/>
|
||||
|
||||
<span id="suspiciousPhoneNumber" style="display:none;">
|
||||
{{ 'MobileMessaging_Settings_SuspiciousPhoneNumber'|translate('54184032') }}
|
||||
<br/><br/>
|
||||
</span>
|
||||
|
||||
+ <input id="countryCallingCode" size="4" maxlength="4"/>
|
||||
<input id="newPhoneNumber"/>
|
||||
<input type="submit" value='{{ 'General_Add'|translate }}'
|
||||
id="addPhoneNumberSubmit"/>
|
||||
<br/>
|
||||
|
||||
<span style=' font-size: 11px;'><span
|
||||
class="form-description">{{ 'MobileMessaging_Settings_CountryCode'|translate }}</span>
|
||||
<span class="form-description"
|
||||
style="margin-left:50px;">{{ 'MobileMessaging_Settings_PhoneNumber'|translate }}</span></span>
|
||||
<br/><br/>
|
||||
|
||||
{{ 'MobileMessaging_Settings_PhoneNumbers_CountryCode_Help'|translate }}
|
||||
|
||||
<select id="countries">
|
||||
{# this is a trick to avoid selecting the first country when no default could be found #}
|
||||
<option value=""> </option>
|
||||
{% for countryCode, country in countries %}
|
||||
<option value='{{ country.countryCallingCode }}'
|
||||
{% if defaultCountry==countryCode %} selected="selected" {% endif %}
|
||||
>
|
||||
{{ country.countryName }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
</td>
|
||||
<td style="width:220px;">
|
||||
{% import 'macros.twig' as piwik %}
|
||||
{{ piwik.inlineHelp(strHelpAddPhone) }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
|
||||
{% if phoneNumbers|length > 0 %}
|
||||
<br/>
|
||||
<br/>
|
||||
<strong>{{ 'MobileMessaging_Settings_ManagePhoneNumbers'|translate }}</strong>
|
||||
<br/>
|
||||
<br/>
|
||||
{% endif %}
|
||||
|
||||
{{ ajax.errorDiv('invalidVerificationCodeAjaxError') }}
|
||||
|
||||
<div id='phoneNumberActivated' style="display:none;">
|
||||
{{ 'MobileMessaging_Settings_PhoneActivated'|translate }}
|
||||
</div>
|
||||
|
||||
<div id='invalidActivationCode' style="display:none;">
|
||||
{{ 'MobileMessaging_Settings_InvalidActivationCode'|translate }}
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
{% for phoneNumber, validated in phoneNumbers %}
|
||||
<li>
|
||||
<span class='phoneNumber'>{{ phoneNumber }}</span>
|
||||
{% if not validated %}
|
||||
<input class='verificationCode'/>
|
||||
<input
|
||||
type='submit'
|
||||
value='{{ 'MobileMessaging_Settings_ValidatePhoneNumber'|translate }}'
|
||||
class='validatePhoneNumberSubmit'
|
||||
/>
|
||||
{% endif %}
|
||||
<input
|
||||
type='submit'
|
||||
value='{{ 'General_Remove'|translate }}'
|
||||
class='removePhoneNumberSubmit'
|
||||
/>
|
||||
{% if not validated %}
|
||||
<br/>
|
||||
<span class='form-description'>{{ 'MobileMessaging_Settings_VerificationCodeJustSent'|translate }}</span>
|
||||
{% endif %}
|
||||
<br/>
|
||||
<br/>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{% if isSuperUser %}
|
||||
<h2>{{ 'MobileMessaging_Settings_SuperAdmin'|translate }}</h2>
|
||||
<table class='adminTable' style='width:650px;'>
|
||||
<tr>
|
||||
<td style="width:400px;">{{ 'MobileMessaging_Settings_LetUsersManageAPICredential'|translate }}</td>
|
||||
<td style="width:250px;">
|
||||
<fieldset>
|
||||
<label>
|
||||
<input
|
||||
type='radio'
|
||||
value='false'
|
||||
name='delegatedManagement' {% if not delegatedManagement %} checked='checked'{% endif %} />
|
||||
{{ 'General_No'|translate }}
|
||||
<br/>
|
||||
<span class='form-description'>
|
||||
({{ 'General_Default'|translate }}
|
||||
) {{ 'MobileMessaging_Settings_LetUsersManageAPICredential_No_Help'|translate }}
|
||||
</span>
|
||||
</label>
|
||||
<br/>
|
||||
<br/>
|
||||
<label>
|
||||
<input
|
||||
type='radio'
|
||||
value='true'
|
||||
name='delegatedManagement' {% if delegatedManagement %} checked='checked'{% endif %} />
|
||||
{{ 'General_Yes'|translate }}
|
||||
<br/>
|
||||
<span class='form-description'>{{ 'MobileMessaging_Settings_LetUsersManageAPICredential_Yes_Help'|translate }}</span>
|
||||
</label>
|
||||
|
||||
</fieldset>
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
{{ ajax.loadingDiv('ajaxLoadingMobileMessagingSettings') }}
|
||||
|
||||
<div class='ui-confirm' id='confirmDeleteAccount'>
|
||||
<h2>{{ 'MobileMessaging_Settings_DeleteAccountConfirm'|translate }}</h2>
|
||||
<input role='yes' type='button' value='{{ 'General_Yes'|translate }}'/>
|
||||
<input role='no' type='button' value='{{ 'General_No'|translate }}'/>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
<tr class='{{ reportType }}'>
|
||||
<td class="first">
|
||||
{{ 'MobileMessaging_PhoneNumbers'|translate }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="entityInlineHelp">
|
||||
{% if phoneNumbers|length == 0 %}
|
||||
{{ 'MobileMessaging_MobileReport_NoPhoneNumbers'|translate }}
|
||||
{% else %}
|
||||
{% for phoneNumber in phoneNumbers %}
|
||||
<label><input name='phoneNumbers' type='checkbox' id='{{ phoneNumber }}'/>{{ phoneNumber }}</label>
|
||||
<br/>
|
||||
{% endfor %}
|
||||
{{ 'MobileMessaging_MobileReport_AdditionalPhoneNumbers'|translate }}
|
||||
{% endif %}
|
||||
<a href='{{ linkTo({'module':"MobileMessaging", 'action': 'index', 'updated':null}) }}'>{{ 'MobileMessaging_MobileReport_MobileMessagingSettingsLink'|translate }}</a>
|
||||
</div>
|
||||
<script>
|
||||
$(function () {
|
||||
resetReportParametersFunctions ['{{ reportType }}'] = function () {
|
||||
var reportParameters = {
|
||||
'phoneNumbers': []
|
||||
};
|
||||
updateReportParametersFunctions['{{ reportType }}'](reportParameters);
|
||||
};
|
||||
|
||||
updateReportParametersFunctions['{{ reportType }}'] = function (reportParameters) {
|
||||
|
||||
if (reportParameters == null) return;
|
||||
|
||||
$('[name=phoneNumbers]').removeProp('checked');
|
||||
$(reportParameters.phoneNumbers).each(function (index, phoneNumber) {
|
||||
$('#\\' + phoneNumber).prop('checked', 'checked');
|
||||
});
|
||||
|
||||
$(document).trigger('ScheduledReport.edit', {});
|
||||
|
||||
};
|
||||
|
||||
getReportParametersFunctions['{{ reportType }}'] = function () {
|
||||
var parameters = Object();
|
||||
var selectedPhoneNumbers = $.map(
|
||||
$('[name=phoneNumbers]').filter(function() {
|
||||
return !this.disabled && this.checked;
|
||||
}),
|
||||
function (phoneNumber) {
|
||||
return $(phoneNumber).attr('id');
|
||||
}
|
||||
);
|
||||
|
||||
// returning [''] when no phone numbers are selected avoids the "please provide a value for 'parameters'" error message
|
||||
parameters.phoneNumbers = selectedPhoneNumbers.length > 0 ? selectedPhoneNumbers : [''];
|
||||
|
||||
return parameters;
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
Loading…
Add table
Add a link
Reference in a new issue