HEX
Server: Microsoft-IIS/8.5
System: Windows NT YDAWBH120 6.3 build 9600 (Windows Server 2012 R2 Standard Edition) AMD64
User: tentjecom_web (0)
PHP: 7.4.14
Disabled: NONE
Upload Files
File: D:/HostingSpaces/PvdBoogaard/indoorski.nl/backup/oude-site/cms/modules/twitter/module.twitter.php
<?php
/**
 * This file contains the iwp_module_twitter class
 *
 * @version $Id$
 * 
 *
 * @package IWP_Modules
 * @subpackage twitter_Module
 */

/**
 * twitter Integration Class
 * This class generates and saves data relating to the twitter module
 *
 * @package IWP_Modules
 * @subpackage twitter_Module
 */

class iwp_module_twitter extends iwp_module {

	public $moduleName = "twitter";
	protected $AppendContent = false;
	public $hasBlocks = true;
	public $tweetCount = 10;

	public $cacheDirs = array('module_twitter'	=> array('expires' => 300, 'extension' => 'html')); // expires in 5 minutes

	protected $layoutBlocks = array(
		array(
			'id'=>'TwitterFollow',
			'name'=>'Follow on Twitter',
		),
		array(
			'id'=>'TwitterList',
			'name'=>'Recent Tweets',
		),

	);

	/**
	 * Instance
	 * This static variable holds the current instance of this object being loaded.
	 * So using the getInstance function anywhere will return the very same instance.
	 *
	 * @var object Instance
	 */
	public static $Instance;

	public $TwitterFollowUser = '';
	public $TwitterFeedUsers = '';

	/**
	 * getInstance
	 * This is a static function that sets up the class instance and stores it to the static variable. It will then return that instantiation in the future.
	 *
	 * @return object Returns the instantiated object
	 **/
	public static function getInstance(){
		if(!isset(self::$Instance)){
			self::$Instance = new self();
		}
		return self::$Instance;
	}

	/**
	 * Constructor
	 *
	 * @return boolean
	 */

	public function __construct(){
		parent::__construct();
	}

	/**
	 * Returns whether or not this module implements content functionality.
	 *
	 * @return boolean
	 */
	public function IsContentModule () { return true; }

	/**
	 * Returns whether or not this module implements a configuration screen
	 *
	 * @return boolean
	 */
	public function HasConfigurationScreen () { return true; }

	/**
	 * Returns whether or not this module implements website-wide functionality.
	 *
	 * @return boolean
	 */
	public function IsWebsiteModule () { return true; }

	/**
	 * @see iwp_module::AdminGetVariablesArray
	 */
	public function AdminGetVariablesArray () {
		return array(
			'twitter_follow',
			'twitter_users',
			'twitter_tweetcount',
			'twitter_message',
		);
	}

	/**
	 * This function returns the array of fields for this module when it is is on a content create/edit page.
	 * It takes the one arguement, which is optional. If provided it will load the data from the database based on the content ID, otherwise
	 * it will return the default array.
	 *
	 * @param integer The ID number of the content item to load.
	 *
	 * @return array An associative array of the fields to display for a content item
	 */
	public function AdminGetContentArray ($id = 0)
	{
		$fields = array();

		$id = (int)$id;

		$fields['posttweet'] = array(
			'type' => 'module_custom:posttweet',
			'default' => 'checked',
			'value' => 'checked'
		);

		if ($id > 0) {
			//$data = $this->db->FetchQuery("SELECT * FROM " . $this->getTable() ." WHERE `id` = " . $id);
			$fields['posttweet']['value'] = '';
		}

		return $fields;
	}

	public function OutputBlock($blockName, $position) {
		$blocks = $this->GetLayoutBlocks();

		if(!isset($blocks[$blockName])){
			return '';
		}

		$data = array();
		$data['lang'] = $this->lang->GetLangVars();
		$this->template->Assign($this->moduleName, $data, false);

		$this->tweetCount =  $this->GetVar('twitter_tweetcount');

		if($blockName == 'TwitterFollow') {
			$this->template->Assign(array($this->moduleName, 'url'), 'http://www.twitter.com/' . $this->TwitterFollowUser , false);
			return $this->template->ParseTemplate('twitter.follow', true, 'twitter');

		}elseif(substr($blockName ,0,strlen('TwitterList')) == 'TwitterList') {
			$this->cache->SetDir('module_twitter');
			$cacheId = $blockName;
			if(!$this->cache->HasExpired($cacheId)){
				return $this->cache->ReadCache($cacheId);
			}
			$tweetFor = str_replace('TwitterList', '', $blockName);

			foreach($this->TwitterFeedUsers as $user) {
				if($user != $tweetFor) {
					continue;
				}

				$transfer = new iwp_transfer();

				$return = $transfer->ReadURL($this->GetStatusURL($user, 'json'));

				$json = json_decode($return);
				if(isset($json->error)){
					return '';
				}

				if(!isset($json[0]->text)) {
					return '';
				}

				$OutputList = array();

				foreach($json as $tweet){
					$OutputList[] = array(
						'tweetText'	=> $tweet->text,
						'tweetHTML' => $this->TweetTextToHTML($tweet->text),
						'tweetTime'	=> iwp_module_twitter_helper::FormatTweetTime($tweet->created_at),
					);
				}

				$this->template->Assign('blockTitle', sprintf($this->lang->Get('LatestTweetsFor'), '@' . $tweetFor ));
				$this->template->Assign('OutputList', $OutputList, false);

				$return = $this->template->ParseTemplate('twitter.feed', true, 'twitter');

				$this->cache->WriteCache($cacheId, $return);
				return $return;
			}

			return '';
		}
	}

	public function TweetTextToHTML ($text) {
		$text = ' '. $text . ' ';

		//	add links to URLs like: www.whatever.com
		$pattern = "#([\s{}\(\)\[\]])([A-Za-z0-9\-\.]+)\.(com|org|net|gov|edu|us|info|biz|ws|name|tv|ee|co|aero|arpa|asia|cat|coop|int|jobs|mil|mobi|museum|pro|tel|travel|ac|ltd)(\.([A-Za-z]{2}))?((?:/[^\s{}\(\)\[\]]*[^\.,\s{}\(\)\[\]]?)?)#ie";
		$text = preg_replace($pattern, "'$1<a href=\"http://$2\" rel=\"nofollow\" target=\"_blank\">'. elipsize('http://$2', 30, false) .'</a>'", $text);

		//	add links to URLs like: http://www.whatever.com
		$pattern = "#([\s{}\(\)\[\]])(([a-z]+?)://([A-Za-z_0-9\-]+\.([^\s{}\(\)\[\]]+[^\s,\.\;{}\(\)\[\]])))#ie";
		$text = preg_replace($pattern, "'$1<a href=\"$2\" rel=\"nofollow\" target=\"_blank\">'. elipsize('$2', 30, false) .'</a>'", $text);

		//	add links to @username
		$count = 1;
		while ($count) {
			//	need to repeat it so we can match instances like "@username1 @username2" where the non-word regex character check overlaps
			$text = preg_replace('#(\W)@(\w{1,15})(\W)#', '$1@<a href="http://twitter.com/$2" target="_blank">$2</a>$3', $text, -1, $count);
		}

		$text = trim($text);
		return $text;
	}

	/**
	 * This function takes care of saving the data posted by the user. It is assumed that when this function is run the ValidateSave() function has
	 * already been run without error. This function can not be run without a valid content ID number.
	 *
	 * @param array $post The array with the posted data
	 * @param integer $contentid The current content id number
	 * @return mixed Array if there is an error, true otherwise
	 */
	function SaveField ($post, $contentid)
	{
		if($contentid < 1){
			return array('Invalid Content ID Number', null);
		}

		if(!isset($post['twitteruserid'])) {
			// no tweet to be posted
			return true;
		}

		if((int)$post['twitteruserid'] < 1){
			return array('Invalid Twitter User', null);
		}

		if(!isset($post['posttweet']) || (isset($post['posttweet']) && $post['posttweet'] != 'checked')) {
			// no tweet to be posted
			return true;
		}

		$tweetTemplate = $this->getTwitterMessageTemplate();
		$title = $post['title'];
		$contentType = iwp_strtolower(iwp_admin_content::getInstance()->ContentType->Get('name_singular'));

		$charsLeft = $currentLength = 0;

		$tweetTemplate = str_replace('{contenttype}', $contentType, $tweetTemplate);
		$tweetTemplate = str_replace('{url}', iwp_config::Get('siteURL') . '/' . $contentid, $tweetTemplate);

		// 7 is the length of {title}
		$currentLength = strlen($tweetTemplate) - 7;
		$charsLeft = 140 - $currentLength;

		if(strlen($title) < $charsLeft) {
			$tweetTemplate = str_replace('{title}', $title, $tweetTemplate);
		} else {
			// make room for an ellipse
			$charsLeft = $charsLeft - 3;
			$tweetTemplate = str_replace('{title}', substr($title, 0, $charsLeft) .  '...', $tweetTemplate);
		}

		$userInfo = $this->db->FetchQuery('select * from ' . $this->getTable('twitter_useraccounts') . ' where id=' . (int)$post['twitteruserid']);

		$return = iwp_module_twitter_helper::makeTwitterPostRequest('statuses/update.json', array('status'=>$tweetTemplate), $userInfo['authtoken']);

		if(is_null($return) || !is_object($return)) {
			return array($this->lang->Get('UnableToTweet'), null);
		}

		return true;
	}


	public function getTwitterMessageTemplate () {
		$template = $this->GetVar('twitter_message');

		if(empty($template)) {
			$this->SetVar('twitter_message', $this->lang->Get('defaultTweetMessage'));
			return $this->lang->Get('defaultTweetMessage');
		}

		return $template;
	}

	public function GetLayoutBlocks(){
		$icon =  IWP_MODULES_URI . '/' . $this->moduleName . '/images/field_icon.png';
		$twitterUsersStr = $this->GetVar('twitter_follow');
		$twitterUser = iwp_module_twitter_helper::convertUserStrToArray($twitterUsersStr);
		$blocks = array();

		if(sizeof($twitterUser) == 1){
			$this->TwitterFollowUser = $twitterUser[0];
			$blocks['TwitterFollow'] = array(
				'id'=>'TwitterFollow',
				'name'=>'Follow on Twitter',
				'icon'=>$icon
			);
		}

		$twitterUsersStr = $this->GetVar('twitter_users');

		$twitterUsers = array();
		$twitterUsers = iwp_module_twitter_helper::convertUserStrToArray($twitterUsersStr);

		if(!empty($twitterUsers)) {
			$this->TwitterFeedUsers = $twitterUsers;
			foreach($twitterUsers as $user){
				$blocks['TwitterList' . $user] = array('id'=>'TwitterList' . $user, 'name'=> sprintf($this->lang->Get('LatestTweetsFor'), '@' . $user), 'icon' => $icon);
			}
		}

		if(empty($blocks)){
			$this->hasBlocks = false;
		}

		return $blocks;
	}

	public function AdminGetContentTypeArray(){
		return array();
	}

	public function remoteEditAccount () {
		if (!$this->auth->HasPerm('core', 'modules', 'configure', 'twitter')) {
			echo GetLang('NoPermissionToConfigureModule');
			die();
		}

		$userId = 0;

		if(isset($_GET['userid'])) {
			$userId = (int)$_GET['userid'];
		}

		if($userId == 0) {
			$this->remoteAddAccount();
			die();
		}

		$userInfo = $this->db->FetchQuery('select * from ' . $this->getTable('twitter_useraccounts') . ' where id=' . $userId);

		if(is_array($userInfo) && !empty($userInfo)) {
			$this->template->Assign('userId', (string)$userId);
			$this->template->Assign('twitterUsername', $userInfo['username']);

			if($userInfo['default'] == 1) {
				$this->template->Assign('twitterDefaultChecked', $this->output->Checked());
			}else{
				$this->template->Assign('twitterDefaultChecked', '');
			}

		}

		// Load the module language variables
		$this->LoadLanguageVariables();
		$this->template->ParseTemplate('twitter.useraccount', false, 'twitter');
	}

	public function remoteAddAccount () {
		if (!$this->auth->HasPerm('core', 'modules', 'configure', 'twitter')) {
			echo GetLang('NoPermissionToConfigureModule');
			die();
		}

		// load any template variables
		$this->template->Assign('userId', '0');

		// Load the module language variables
		$this->LoadLanguageVariables();
		$this->template->ParseTemplate('twitter.useraccount', false, 'twitter');
	}

	public function remoteDeleteAccount () {
		if (!$this->auth->HasPerm('core', 'modules', 'configure', 'twitter')) {
			die(json_encode(array(
				'success' => false,
				'message' => GetLang('NoPermissionToConfigureModule'),
			)));
		}

		if (!isset($_POST['userid'])) {
			die(json_encode(array(
				'success' => false,
				'message' => $this->lang->Get('InvalidUserData'),
			)));
		}

		$userId = (int)$_POST['userid'];

		if ($userId < 1) {
			die(json_encode(array(
				'success' => false,
				'message' => $this->lang->Get('InvalidUserData'),
			)));
		}

		if($this->db->Query('delete from ' . $this->getTable('twitter_useraccounts') . ' where id=' . $userId)) {
			die(json_encode(array(
				'success' => true,
				'message' => $this->lang->Get('UserAccountDeleteSuccess'),
				'userid'  => $userId,
			)));
		}

		die(json_encode(array(
			'success' => false,
			'message' => $this->lang->Get('MySQLUserDeleteError') . $this->db->GetErrorMsg(),
		)));
	}

	public function remoteSaveAccount () {

		if (!$this->auth->HasPerm('core', 'modules', 'configure', 'twitter')) {
			die(json_encode(array(
				'success' => false,
				'message' => GetLang('NoPermissionToConfigureModule'),
			)));
		}

		if(!isset($_POST['username']) || !isset($_POST['password']) || !isset($_POST['userid']) || !isset($_POST['default'])) {
			die(json_encode(array(
				'success' => false,
				'message' => $this->lang->Get('InvalidUserData'),
			)));
		}

		$default  = 0;
		$username = trim($_POST['username']);
		$password = trim($_POST['password']);
		$userid   = (int)($_POST['userid']);


		if($_POST['default'] == 'checked') {
			$default = 1;
		}

		if(empty($username)) {
			die(json_encode(array(
				'success' => false,
				'message' => $this->lang->Get('EnterUsername'),
			)));
		}


		if(empty($password) && $userid === 0) {
			die(json_encode(array(
				'success' => false,
				'message' => $this->lang->Get('EnterPassword'),
			)));
		}

		if($userid === 0) {
			// they're adding a new user
			// create the user token, ensuring the user is valid
			$userToken = base64_encode($username . ':' . $password);

		} else {
			// they're editing an existing user
			$userInfo = $this->db->FetchQuery('select * from ' . $this->getTable('twitter_useraccounts') . ' where id=' . $userid);
			// create the user token, ensuring the user is valid
			$userToken = $userInfo['authtoken'];
		}

		$return = iwp_module_twitter_helper::makeTwitterGetRequest('account/verify_credentials.json', '', $userToken);

		if(is_null($return) || !is_object($return)) {
			die(json_encode(array(
				'success' => false,
				'message' => $this->lang->Get('InvalidTwitterAccount'),
			)));
		}

		// success, twitter recognises them!
		$userData = array(
			'username'  => $username,
			'authtoken' => $userToken,
			'fullname'  => $return->name,
			'default'   => $default,
		);

		if($userid === 0) {
			// they're adding a new user
			if($this->db->InsertQuery($this->getTable('twitter_useraccounts'), $userData)) {
				die(json_encode(array(
					'success' => true,
					'insert' => true,
					'userid'  => $this->db->LastId(),
					'name'    => $return->name . ' (' . $username . ')',
					'message' => $this->lang->Get('UserAccountSaveSuccess'),
				)));
			}
		} else {
			// they're editing an existing user
			if($this->db->UpdateQuery($this->getTable('twitter_useraccounts'), $userData, 'id=' . $userid)) {
				die(json_encode(array(
					'success' => true,
					'insert' => false,
					'userid'  => $userid,
					'name'    => $return->name . ' (' . $username . ')',
					'message' => $this->lang->Get('UserAccountSaveSuccess'),
				)));
			}
		}

		die(json_encode(array(
			'success' => false,
			'message' => $this->lang->Get('MySQLUserSaveError') . $this->db->GetErrorMsg(),
		)));

	}

	/**
	 * An array of all the database tables that this module uses. These names will be appended with the module table prefix.
	 *
	 * @var array
	 */

	protected $dbTables = array(
		'twitter_useraccounts',
	);


	/**
	 * Returns a list of database tables for this module.
	 *
	 * @param boolean $withoutPrefix A boolean for whether or not to include the prefix for the table.
	 *
	 * @return string
	 */
	public function getTables($withoutPrefix=false) {
		if($withoutPrefix) {
			return $this->dbTables;
		}

		$tables = $this->dbTables;

		foreach($tables as $k=>$table ){
			$tables[$k] = IWP_MODULE_DB_PREFIX . $table;
		}

		return $tables;
	}

	/**
	 * This function builds the SQL for the database tables used by this module. It uses the iwp_tablecreator to do so.
	 * It sets the member variables table and tableSchema with the objects and final SQL.
	 * @return void
	 *
	 * @see iwp_tablecreator
	 */
	public function CreateModuleTable ()
	{
		//	create statements should match a SHOW CREATE result, with cr/lf chars stripped out
		$userAccountsTableName = $this->getTable('twitter_useraccounts');

		// primary table, "iwp_module_galleries"
		$settingsTable = new iwp_tablecreator($userAccountsTableName);

		$settingsTable->AddField('id')->SetAsPrimaryKey();
		$settingsTable->AddField('username')->SetAsVarChar('255');
		$settingsTable->AddField('fullname')->SetAsVarChar('255');
		$settingsTable->AddField('authtoken')->SetAsVarChar('255');
		$settingsTable->AddField('default')->SetAsInt();

		$this->table = array(&$settingsTable);

		$this->tableSchema = array(
			$userAccountsTableName => $settingsTable->GetCreateTable(),
		);
	}

	/**
	 * Called by the module framework when the configuration screen is requested.
	 *
	 * @return void
	 */
	public function AdminConfigure ()
	{
		$this->form->EnableTabs = false;

		$this->form->AddGroup($this->lang->Get('SiteLayoutBlocks'));

		$field = $this->form->AddField('textbox', 'twitter_follow', null, $this->lang);
		$field->Append('<div class="aside">' . $this->lang->Get('field_twitter_follow_Example') . '</div>');

		$field = $this->form->AddField('textbox', 'twitter_users', null, $this->lang);
		$field->Append('<div class="aside">' . $this->lang->Get('field_twitter_users_Example') . '</div>');

		$field = $this->form->AddField('textbox', 'twitter_tweetcount', null, $this->lang)->Value(10);




		//$field->Append('<div class="aside">' . $this->lang->Get('field_twitter_users_Example') . '</div>');

		$this->form->AddGroup($this->lang->Get('automaticTweetPosting'));

		$field = $this->form->AddField('textbox', 'twitter_message', null, $this->lang)->DisableLabel()->Value($this->lang->Get('defaultTweetMessage'));
		$field = $this->form->AddField(array('module_custom:twitterusers', 'twitter'), 'twitter_useraccounts', null, $this->lang);

	}

	public function GetStatusURL($user, $method='json') {
		return 'http://twitter.com/statuses/user_timeline/' . $user .'.' . $method . '?count=' . $this->tweetCount;
	}

	/**
	 * Apply module-specific filtering to configure screen data before it is sent to the database
	 *
	 * @param array $data
	 */
	public function AdminConfigureSave (&$data)
	{
		$user = str_replace('@', '', $data['twitter_follow']);
		$finishedUser = '';
		$returnStatus = array();

		$transfer = new iwp_transfer();

		$user = trim($user);
		if(!empty($user)){
			$return = $transfer->ReadURL($this->GetStatusURL($user, 'xml'));
			if(empty($return) || in_string('<error>Not found</error>', $return)) {
				// user doesn't exist
				$returnStatus[] = sprintf($this->lang->Get('TwitterUserNotExist'), $user);
			} else {
				// user does exist
				$finishedUser = '@' . $user;
			}
		}

		$data['twitter_follow'] = $finishedUser;
		$data['twitter_tweetcount'] = max((int)$data['twitter_tweetcount'], 1);

		$users = iwp_module_twitter_helper::convertUserStrToArray($data['twitter_users']);
		$finishedUsers = array();

		foreach($users as $user) {
			$user = trim($user);
			if(empty($user)){
				continue;
			}
			$return = $transfer->ReadURL($this->GetStatusURL($user, 'xml'));

			if(empty($return) || in_string('<error>Not found</error>', $return)) {
				// user doesn't exist
				$returnStatus[] = sprintf($this->lang->Get('TwitterUserNotExist'), $user);
			} else {
				// user does exist
				$finishedUsers[] = '@' . $user;
			}
		}

		$data['twitter_users'] = implode(', ', $finishedUsers);

		if(empty($returnStatus)){
			return true;
		}

		return $returnStatus;
	}
}


class iwp_module_twitter_helper {
	public static function formatTweetTime($timeStr){
		$timestamp	= strtotime($timeStr);
		$now		= time();
		$oneDay		= 60 * 60 * 24;

		if($now < $timestamp || $timestamp > ($now - $oneDay)){
			// if the timestamp is in the future, or within the last 24 hours, mark as 'today'
			$hoursAgo = round((($now - $timestamp)/60)/60,0);
			return $hoursAgo . ' Hours Ago';
		}

		if($timestamp > ($now - (7 * $oneDay))) {
			// within the last week
			$difference = $now - $timestamp;
			$days = ceil(((($difference/60)/60)/24));
			if($days < 2){
				return '1 Day Ago';
			}else{
				return $days . ' Days Ago';
			}
		}else{
			// older than a week
			$difference = $now - $timestamp;
			$days = round((((($difference/60)/60)/24)/7), 0);
			if($days < 2){
				return '1 Week Ago';
			}else{
				return $days . ' Weeks Ago';
			}
		}

		return $timeStr;
	}


	public static function convertUserStrToArray($userString){
		$userString = str_replace('@', '', $userString);
		return preg_split('#,\s*#', $userString, -1, PREG_SPLIT_NO_EMPTY);
	}

	public static function makeTwitterPostRequest($url, $postData='', $authToken='') {
		$transfer = new iwp_transfer();
		$headers = array();

		if(!empty($authToken)) {
			$headers = array('Authorization: Basic ' . $authToken);
		}

		if(!is_array($postData)) {
			$postData = array();
		}

		$return = $transfer->SendPOSTRequest('http://twitter.com/' . $url, $postData,  $headers);

		$json = json_decode($return);

		return $json;
	}

	public static function makeTwitterGetRequest($url, $postData='', $authToken='') {
		$transfer = new iwp_transfer();
		$headers = array();

		if(is_array($postData)) {
			$postData = '?' . $transfer->ArrayToQueryString($postData);
		}elseif(!empty($postData)) {
			$postData = '?' . $postData;
		}

		if(!empty($authToken)) {
			$headers = array('Authorization: Basic ' . $authToken);
		}

		$return = $transfer->ReadURL('http://twitter.com/' . $url . $postData, $headers);

		$json = json_decode($return);

		return $json;
	}
}