diff --git a/appnet/AppDotNet.php b/appnet/AppDotNet.php
index 32361314..3b116d03 100644
--- a/appnet/AppDotNet.php
+++ b/appnet/AppDotNet.php
@@ -2,7 +2,7 @@
/**
* AppDotNet.php
* App.net PHP library
- * https://github.com/jdolitsky/AppDotNetPHP
+ * https://github.com/jdolitsky/AppDotNetPHP.
*
* This class handles a lower level type of access to App.net. It's ideal
* for command line scripts and other places where you want full control
@@ -13,1635 +13,1840 @@
* etc. EZAppDotNet assumes you're accessing App.net via a browser, whereas
* this class tries to make no assumptions at all.
*/
-class AppDotNet {
+class AppDotNet
+{
+ protected $_baseUrl = 'https://alpha-api.app.net/stream/0/';
+ protected $_authUrl = 'https://account.app.net/oauth/';
- protected $_baseUrl = 'https://alpha-api.app.net/stream/0/';
- protected $_authUrl = 'https://account.app.net/oauth/';
+ private $_authPostParams = array();
- private $_authPostParams=array();
+ // stores the access token after login
+ private $_accessToken = null;
- // stores the access token after login
- private $_accessToken = null;
+ // stores the App access token if we have it
+ private $_appAccessToken = null;
- // stores the App access token if we have it
- private $_appAccessToken = null;
+ // stores the user ID returned when fetching the auth token
+ private $_user_id = null;
- // stores the user ID returned when fetching the auth token
- private $_user_id = null;
+ // stores the username returned when fetching the auth token
+ private $_username = null;
- // stores the username returned when fetching the auth token
- private $_username = null;
-
- // The total number of requests you're allowed within the alloted time period
- private $_rateLimit = null;
-
- // The number of requests you have remaining within the alloted time period
- private $_rateLimitRemaining = null;
-
- // The number of seconds remaining in the alloted time period
- private $_rateLimitReset = null;
-
- // The scope the user has
- private $_scope = null;
-
- // token scopes
- private $_scopes=array();
-
- // debug info
- private $_last_request = null;
- private $_last_response = null;
-
- // ssl certification
- private $_sslCA = null;
-
- // the callback function to be called when an event is received from the stream
- private $_streamCallback = null;
-
- // the stream buffer
- private $_streamBuffer = '';
-
- // stores the curl handler for the current stream
- private $_currentStream = null;
-
- // stores the curl multi handler for the current stream
- private $_multiStream = null;
-
- // stores the number of failed connects, so we can back off multiple failures
- private $_connectFailCounter = 0;
-
- // stores the most recent stream url, so we can re-connect when needed
- private $_streamUrl = null;
-
- // keeps track of the last time we've received a packet from the api, if it's too long we'll reconnect
- private $_lastStreamActivity = null;
-
- // stores the headers received when connecting to the stream
- private $_streamHeaders = null;
-
- // response meta max_id data
- private $_maxid = null;
-
- // response meta min_id data
- private $_minid = null;
-
- // response meta more data
- private $_more = null;
-
- // response stream marker data
- private $_last_marker = null;
-
- // strip envelope response from returned value
- private $_stripResponseEnvelope=true;
-
- // if processing stream_markers or any fast stream, decrease $sleepFor
- public $streamingSleepFor=20000;
-
- /**
- * Constructs an AppDotNet PHP object with the specified client ID and
- * client secret.
- * @param string $client_id The client ID you received from App.net when
- * creating your app.
- * @param string $client_secret The client secret you received from
- * App.net when creating your app.
- */
- public function __construct($client_id,$client_secret) {
- $this->_clientId = $client_id;
- $this->_clientSecret = $client_secret;
-
- // if the digicert certificate exists in the same folder as this file,
- // remember that fact for later
- if (file_exists(dirname(__FILE__).'/DigiCertHighAssuranceEVRootCA.pem')) {
- $this->_sslCA = dirname(__FILE__).'/DigiCertHighAssuranceEVRootCA.pem';
- }
- }
-
- /**
- * Set whether or not to strip Envelope Response (meta) information
- * This option will be deprecated in the future. Is it to allow
- * a stepped migration path between code expecting the old behavior
- * and new behavior. When not stripped, you still can use the proper
- * method to pull the meta information. Please start converting your code ASAP
- */
- public function includeResponseEnvelope() {
- $this->_stripResponseEnvelope=false;
- }
-
- /**
- * Construct the proper Auth URL for the user to visit and either grant
- * or not access to your app. Usually you would place this as a link for
- * the user to client, or a redirect to send them to the auth URL.
- * Also can be called after authentication for additional scopes
- * @param string $callbackUri Where you want the user to be directed
- * after authenticating with App.net. This must be one of the URIs
- * allowed by your App.net application settings.
- * @param array $scope An array of scopes (permissions) you wish to obtain
- * from the user. Currently options are stream, email, write_post, follow,
- * messages, and export. If you don't specify anything, you'll only receive
- * access to the user's basic profile (the default).
- */
- public function getAuthUrl($callback_uri,$scope=null) {
-
- // construct an authorization url based on our client id and other data
- $data = array(
- 'client_id'=>$this->_clientId,
- 'response_type'=>'code',
- 'redirect_uri'=>$callback_uri,
- );
-
- $url = $this->_authUrl;
- if ($this->_accessToken) {
- $url .= 'authorize?';
- } else {
- $url .= 'authenticate?';
- }
- $url .= $this->buildQueryString($data);
-
- if ($scope) {
- $url .= '&scope='.implode('+',$scope);
- }
-
- // return the constructed url
- return $url;
- }
-
- /**
- * Call this after they return from the auth page, or anytime you need the
- * token. For example, you could store it in a database and use
- * setAccessToken() later on to return on behalf of the user.
- */
- public function getAccessToken($callback_uri) {
- // if there's no access token set, and they're returning from
- // the auth page with a code, use the code to get a token
- if (!$this->_accessToken && isset($_GET['code']) && $_GET['code']) {
-
- // construct the necessary elements to get a token
- $data = array(
- 'client_id'=>$this->_clientId,
- 'client_secret'=>$this->_clientSecret,
- 'grant_type'=>'authorization_code',
- 'redirect_uri'=>$callback_uri,
- 'code'=>$_GET['code']
- );
-
- // try and fetch the token with the above data
- $res = $this->httpReq('post',$this->_authUrl.'access_token', $data);
-
- // store it for later
- $this->_accessToken = $res['access_token'];
- $this->_username = $res['username'];
- $this->_user_id = $res['user_id'];
- }
-
- // return what we have (this may be a token, or it may be nothing)
- return $this->_accessToken;
- }
-
- /**
- * Check the scope of current token to see if it has required scopes
- * has to be done after a check
- */
- public function checkScopes($app_scopes) {
- if (!count($this->_scopes)) {
- return -1; // _scope is empty
- }
- $missing=array();
- foreach($app_scopes as $scope) {
- if (!in_array($scope,$this->_scopes)) {
- if ($scope=='public_messages') {
- // messages works for public_messages
- if (in_array('messages',$this->_scopes)) {
- // if we have messages in our scopes
- continue;
- }
- }
- $missing[]=$scope;
- }
- }
- // identify the ones missing
- if (count($missing)) {
- // do something
- return $missing;
- }
- return 0; // 0 missing
- }
-
- /**
- * Set the access token (eg: after retrieving it from offline storage)
- * @param string $token A valid access token you're previously received
- * from calling getAccessToken().
- */
- public function setAccessToken($token) {
- $this->_accessToken = $token;
- }
-
- /**
- * Deauthorize the current token (delete your authorization from the API)
- * Generally this is useful for logging users out from a web app, so they
- * don't get automatically logged back in the next time you redirect them
- * to the authorization URL.
- */
- public function deauthorizeToken() {
- return $this->httpReq('delete',$this->_baseUrl.'token');
- }
-
- /**
- * Retrieve an app access token from the app.net API. This allows you
- * to access the API without going through the user access flow if you
- * just want to (eg) consume global. App access tokens are required for
- * some actions (like streaming global). DO NOT share the return value
- * of this function with any user (or save it in a cookie, etc). This
- * is considered secret info for your app only.
- * @return string The app access token
- */
- public function getAppAccessToken() {
-
- // construct the necessary elements to get a token
- $data = array(
- 'client_id'=>$this->_clientId,
- 'client_secret'=>$this->_clientSecret,
- 'grant_type'=>'client_credentials',
- );
-
- // try and fetch the token with the above data
- $res = $this->httpReq('post',$this->_authUrl.'access_token', $data);
-
- // store it for later
- $this->_appAccessToken = $res['access_token'];
- $this->_accessToken = $res['access_token'];
- $this->_username = null;
- $this->_user_id = null;
-
- return $this->_accessToken;
- }
-
- /**
- * Returns the total number of requests you're allowed within the
- * alloted time period.
- * @see getRateLimitReset()
- */
- public function getRateLimit() {
- return $this->_rateLimit;
- }
-
- /**
- * The number of requests you have remaining within the alloted time period
- * @see getRateLimitReset()
- */
- public function getRateLimitRemaining() {
- return $this->_rateLimitRemaining;
- }
-
- /**
- * The number of seconds remaining in the alloted time period.
- * When this time is up you'll have getRateLimit() available again.
- */
- public function getRateLimitReset() {
- return $this->_rateLimitReset;
- }
-
- /**
- * The scope the user has
- */
- public function getScope() {
- return $this->_scope;
- }
-
- /**
- * Internal function, parses out important information App.net adds
- * to the headers.
- */
- protected function parseHeaders($response) {
- // take out the headers
- // set internal variables
- // return the body/content
- $this->_rateLimit = null;
- $this->_rateLimitRemaining = null;
- $this->_rateLimitReset = null;
- $this->_scope = null;
-
- $response = explode("\r\n\r\n",$response,2);
- $headers = $response[0];
-
- if($headers == 'HTTP/1.1 100 Continue') {
- $response = explode("\r\n\r\n",$response[1],2);
- $headers = $response[0];
- }
-
- if (isset($response[1])) {
- $content = $response[1];
- }
- else {
- $content = null;
- }
-
- // this is not a good way to parse http headers
- // it will not (for example) take into account multiline headers
- // but what we're looking for is pretty basic, so we can ignore those shortcomings
- $headers = explode("\r\n",$headers);
- foreach ($headers as $header) {
- $header = explode(': ',$header,2);
- if (count($header)<2) {
- continue;
- }
- list($k,$v) = $header;
- switch ($k) {
- case 'X-RateLimit-Remaining':
- $this->_rateLimitRemaining = $v;
- break;
- case 'X-RateLimit-Limit':
- $this->_rateLimit = $v;
- break;
- case 'X-RateLimit-Reset':
- $this->_rateLimitReset = $v;
- break;
- case 'X-OAuth-Scopes':
- $this->_scope = $v;
- $this->_scopes=explode(',',$v);
- break;
- }
- }
- return $content;
- }
-
- /**
- * Internal function. Used to turn things like TRUE into 1, and then
- * calls http_build_query.
- */
- protected function buildQueryString($array) {
- foreach ($array as $k=>&$v) {
- if ($v===true) {
- $v = '1';
- }
- elseif ($v===false) {
- $v = '0';
- }
- unset($v);
- }
- return http_build_query($array);
- }
-
-
- /**
- * Internal function to handle all
- * HTTP requests (POST,PUT,GET,DELETE)
- */
- protected function httpReq($act, $req, $params=array(),$contentType='application/x-www-form-urlencoded') {
- $ch = curl_init($req);
- $headers = array();
- if($act != 'get') {
- curl_setopt($ch, CURLOPT_POST, true);
- // if they passed an array, build a list of parameters from it
- if (is_array($params) && $act != 'post-raw') {
- $params = $this->buildQueryString($params);
- }
- curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
- $headers[] = "Content-Type: ".$contentType;
- }
- if($act != 'post' && $act != 'post-raw') {
- curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($act));
- }
- if($act == 'get' && isset($params['access_token'])) {
- $headers[] = 'Authorization: Bearer '.$params['access_token'];
- }
- else if ($this->_accessToken) {
- $headers[] = 'Authorization: Bearer '.$this->_accessToken;
- }
- curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLINFO_HEADER_OUT, true);
- curl_setopt($ch, CURLOPT_HEADER, true);
- if ($this->_sslCA) {
- curl_setopt($ch, CURLOPT_CAINFO, $this->_sslCA);
- }
- $this->_last_response = curl_exec($ch);
- $this->_last_request = curl_getinfo($ch,CURLINFO_HEADER_OUT);
- $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
- if ($http_status==0) {
- throw new AppDotNetException('Unable to connect to '.$req);
- }
- if ($http_status<200 || $http_status>=300) {
- throw new AppDotNetException('HTTP error '.$this->_last_response);
- }
- if ($this->_last_request===false) {
- if (!curl_getinfo($ch,CURLINFO_SSL_VERIFYRESULT)) {
- throw new AppDotNetException('SSL verification failed, connection terminated.');
- }
- }
- $response = $this->parseHeaders($this->_last_response);
- $response = json_decode($response,true);
-
- if (isset($response['meta'])) {
- if (isset($response['meta']['max_id'])) {
- $this->_maxid=$response['meta']['max_id'];
- $this->_minid=$response['meta']['min_id'];
- }
- if (isset($response['meta']['more'])) {
- $this->_more=$response['meta']['more'];
- }
- if (isset($response['meta']['marker'])) {
- $this->_last_marker=$response['meta']['marker'];
- }
- }
-
- // look for errors
- if (isset($response['error'])) {
- if (is_array($response['error'])) {
- throw new AppDotNetException($response['error']['message'],
- $response['error']['code']);
- }
- else {
- throw new AppDotNetException($response['error']);
- }
- }
-
- // look for response migration errors
- elseif (isset($response['meta']) && isset($response['meta']['error_message'])) {
- throw new AppDotNetException($response['meta']['error_message'],$response['meta']['code']);
- }
-
- // if we've received a migration response, handle it and return data only
- elseif ($this->_stripResponseEnvelope && isset($response['meta']) && isset($response['data'])) {
- return $response['data'];
- }
-
- // else non response migration response, just return it
- else {
- return $response;
- }
- }
-
-
- /**
- * Get max_id from last meta response data envelope
- */
- public function getResponseMaxID() {
- return $this->_maxid;
- }
-
- /**
- * Get min_id from last meta response data envelope
- */
- public function getResponseMinID() {
- return $this->_minid;
- }
-
- /**
- * Get more from last meta response data envelope
- */
- public function getResponseMore() {
- return $this->_more;
- }
-
- /**
- * Get marker from last meta response data envelope
- */
- public function getResponseMarker() {
- return $this->_last_marker;
- }
-
- /**
- * Fetch API configuration object
- */
- public function getConfig() {
- return $this->httpReq('get',$this->_baseUrl.'config');
- }
-
- /**
- * Return the Filters for the current user.
- */
- public function getAllFilters() {
- return $this->httpReq('get',$this->_baseUrl.'filters');
- }
-
- /**
- * Create a Filter for the current user.
- * @param string $name The name of the new filter
- * @param array $filters An associative array of filters to be applied.
- * This may change as the API evolves, as of this writing possible
- * values are: user_ids, hashtags, link_domains, and mention_user_ids.
- * You will need to provide at least one filter name=>value pair.
- */
- public function createFilter($name='New filter', $filters=array()) {
- $filters['name'] = $name;
- return $this->httpReq('post',$this->_baseUrl.'filters',$filters);
- }
-
- /**
- * Returns a specific Filter object.
- * @param integer $filter_id The ID of the filter you wish to retrieve.
- */
- public function getFilter($filter_id=null) {
- return $this->httpReq('get',$this->_baseUrl.'filters/'.urlencode($filter_id));
- }
-
- /**
- * Delete a Filter. The Filter must belong to the current User.
- * @return object Returns the deleted Filter on success.
- */
- public function deleteFilter($filter_id=null) {
- return $this->httpReq('delete',$this->_baseUrl.'filters/'.urlencode($filter_id));
- }
-
- /**
- * Process user description, message or post text.
- * Mentions and hashtags will be parsed out of the
- * text, as will bare URLs. To create a link in the text without using a
- * bare URL, include the anchor text in the object text and include a link
- * entity in the function call.
- * @param string $text The text of the description/message/post
- * @param array $data An associative array of optional post data. This
- * will likely change as the API evolves, as of this writing allowed keys are:
- * reply_to, and annotations. "annotations" may be a complex object represented
- * by an associative array.
- * @param array $params An associative array of optional data to be included
- * in the URL (such as 'include_annotations' and 'include_machine')
- * @return array An associative array representing the post.
- */
- public function processText($text=null, $data = array(), $params = array()) {
- $data['text'] = $text;
- $json = json_encode($data);
- $qs = '';
- if (!empty($params)) {
- $qs = '?'.$this->buildQueryString($params);
- }
- return $this->httpReq('post',$this->_baseUrl.'text/process'.$qs, $json, 'application/json');
- }
-
- /**
- * Create a new Post object. Mentions and hashtags will be parsed out of the
- * post text, as will bare URLs. To create a link in a post without using a
- * bare URL, include the anchor text in the post's text and include a link
- * entity in the post creation call.
- * @param string $text The text of the post
- * @param array $data An associative array of optional post data. This
- * will likely change as the API evolves, as of this writing allowed keys are:
- * reply_to, and annotations. "annotations" may be a complex object represented
- * by an associative array.
- * @param array $params An associative array of optional data to be included
- * in the URL (such as 'include_annotations' and 'include_machine')
- * @return array An associative array representing the post.
- */
- public function createPost($text=null, $data = array(), $params = array()) {
- $data['text'] = $text;
-
- $json = json_encode($data);
- $qs = '';
- if (!empty($params)) {
- $qs = '?'.$this->buildQueryString($params);
- }
- return $this->httpReq('post',$this->_baseUrl.'posts'.$qs, $json, 'application/json');
- }
-
- /**
- * Returns a specific Post.
- * @param integer $post_id The ID of the post to retrieve
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: include_annotations.
- * @return array An associative array representing the post
- */
- public function getPost($post_id=null,$params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'posts/'.urlencode($post_id)
- .'?'.$this->buildQueryString($params));
- }
-
- /**
- * Delete a Post. The current user must be the same user who created the Post.
- * It returns the deleted Post on success.
- * @param integer $post_id The ID of the post to delete
- * @param array An associative array representing the post that was deleted
- */
- public function deletePost($post_id=null) {
- return $this->httpReq('delete',$this->_baseUrl.'posts/'.urlencode($post_id));
- }
-
- /**
- * Retrieve the Posts that are 'in reply to' a specific Post.
- * @param integer $post_id The ID of the post you want to retrieve replies for.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function getPostReplies($post_id=null,$params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'posts/'.urlencode($post_id)
- .'/replies?'.$this->buildQueryString($params));
- }
-
- /**
- * Get the most recent Posts created by a specific User in reverse
- * chronological order (most recent first).
- * @param mixed $user_id Either the ID of the user you wish to retrieve posts by,
- * or the string "me", which will retrieve posts for the user you're authenticated
- * as.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function getUserPosts($user_id='me', $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'users/'.urlencode($user_id)
- .'/posts?'.$this->buildQueryString($params));
- }
-
- /**
- * Get the most recent Posts mentioning by a specific User in reverse
- * chronological order (newest first).
- * @param mixed $user_id Either the ID of the user who is being mentioned, or
- * the string "me", which will retrieve posts for the user you're authenticated
- * as.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function getUserMentions($user_id='me',$params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'users/'
- .urlencode($user_id).'/mentions?'.$this->buildQueryString($params));
- }
-
- /**
- * Return the 20 most recent posts from the current User and
- * the Users they follow.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function getUserStream($params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'posts/stream?'.$this->buildQueryString($params));
- }
-
- /**
- * Returns a specific user object.
- * @param mixed $user_id The ID of the user you want to retrieve, or the string
- * "me" to retrieve data for the users you're currently authenticated as.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: include_annotations|include_user_annotations.
- * @return array An associative array representing the user data.
- */
- public function getUser($user_id='me', $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'users/'.urlencode($user_id)
- .'?'.$this->buildQueryString($params));
- }
-
- /**
- * Returns multiple users request by an array of user ids
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: include_annotations|include_user_annotations.
- * @return array An associative array representing the users data.
- */
- public function getUsers($user_arr, $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'users?ids='.join(',',$user_arr)
- .'&'.$this->buildQueryString($params));
- }
-
- /**
- * Add the specified user ID to the list of users followed.
- * Returns the User object of the user being followed.
- * @param integer $user_id The user ID of the user to follow.
- * @return array An associative array representing the user you just followed.
- */
- public function followUser($user_id=null) {
- return $this->httpReq('post',$this->_baseUrl.'users/'.urlencode($user_id).'/follow');
- }
-
- /**
- * Removes the specified user ID to the list of users followed.
- * Returns the User object of the user being unfollowed.
- * @param integer $user_id The user ID of the user to unfollow.
- * @return array An associative array representing the user you just unfollowed.
- */
- public function unfollowUser($user_id=null) {
- return $this->httpReq('delete',$this->_baseUrl.'users/'.urlencode($user_id).'/follow');
- }
-
- /**
- * Returns an array of User objects the specified user is following.
- * @param mixed $user_id Either the ID of the user being followed, or
- * the string "me", which will retrieve posts for the user you're authenticated
- * as.
- * @return array An array of associative arrays, each representing a single
- * user following $user_id
- */
- public function getFollowing($user_id='me') {
- return $this->httpReq('get',$this->_baseUrl.'users/'.$user_id.'/following');
- }
-
- /**
- * Returns an array of User objects for users following the specified user.
- * @param mixed $user_id Either the ID of the user being followed, or
- * the string "me", which will retrieve posts for the user you're authenticated
- * as.
- * @return array An array of associative arrays, each representing a single
- * user following $user_id
- */
- public function getFollowers($user_id='me') {
- return $this->httpReq('get',$this->_baseUrl.'users/'.$user_id.'/followers');
- }
-
- /**
- * Return Posts matching a specific #hashtag.
- * @param string $hashtag The hashtag you're looking for.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function searchHashtags($hashtag=null, $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'posts/tag/'
- .urlencode($hashtag).'?'.$this->buildQueryString($params));
- }
-
- /**
- * Retrieve a list of all public Posts on App.net, often referred to as the
- * global stream.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function getPublicPosts($params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'posts/stream/global?'.$this->buildQueryString($params));
- }
-
- /**
- * List User interactions
- */
- public function getMyInteractions($params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'users/me/interactions?'.$this->buildQueryString($params));
- }
-
- /**
- * Retrieve a user's user ID by specifying their username.
- * Now supported by the API. We use the API if we have a token
- * Otherwise we scrape the alpha.app.net site for the info.
- * @param string $username The username of the user you want the ID of, without
- * an @ symbol at the beginning.
- * @return integer The user's user ID
- */
- public function getIdByUsername($username=null) {
- if ($this->_accessToken) {
- $res=$this->httpReq('get',$this->_baseUrl.'users/@'.$username);
- $user_id=$res['data']['id'];
- } else {
- $ch = curl_init('https://alpha.app.net/'.urlencode(strtolower($username)));
- curl_setopt($ch, CURLOPT_POST, false);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch,CURLOPT_USERAGENT,
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:7.0.1) Gecko/20100101 Firefox/7.0.1');
- $response = curl_exec($ch);
- curl_close($ch);
- $temp = explode('title="User Id ',$response);
- $temp2 = explode('"',$temp[1]);
- $user_id = $temp2[0];
- }
- return $user_id;
- }
-
- /**
- * Mute a user
- * @param integer $user_id The user ID to mute
- */
- public function muteUser($user_id=null) {
- return $this->httpReq('post',$this->_baseUrl.'users/'.urlencode($user_id).'/mute');
- }
-
- /**
- * Unmute a user
- * @param integer $user_id The user ID to unmute
- */
- public function unmuteUser($user_id=null) {
- return $this->httpReq('delete',$this->_baseUrl.'users/'.urlencode($user_id).'/mute');
- }
-
- /**
- * List the users muted by the current user
- * @return array An array of associative arrays, each representing one muted user.
- */
- public function getMuted() {
- return $this->httpReq('get',$this->_baseUrl.'users/me/muted');
- }
-
- /**
- * Star a post
- * @param integer $post_id The post ID to star
- */
- public function starPost($post_id=null) {
- return $this->httpReq('post',$this->_baseUrl.'posts/'.urlencode($post_id).'/star');
- }
-
- /**
- * Unstar a post
- * @param integer $post_id The post ID to unstar
- */
- public function unstarPost($post_id=null) {
- return $this->httpReq('delete',$this->_baseUrl.'posts/'.urlencode($post_id).'/star');
- }
-
- /**
- * List the posts starred by the current user
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * See https://github.com/appdotnet/api-spec/blob/master/resources/posts.md#general-parameters
- * @return array An array of associative arrays, each representing a single
- * user who has starred a post
- */
- public function getStarred($user_id='me', $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'users/'.urlencode($user_id).'/stars'
- .'?'.$this->buildQueryString($params));
- }
-
- /**
- * List the users who have starred a post
- * @param integer $post_id the post ID to get stars from
- * @return array An array of associative arrays, each representing one user.
- */
- public function getStars($post_id=null) {
- return $this->httpReq('get',$this->_baseUrl.'posts/'.urlencode($post_id).'/stars');
- }
-
- /**
- * Returns an array of User objects of users who reposted the specified post.
- * @param integer $post_id the post ID to
- * @return array An array of associative arrays, each representing a single
- * user who reposted $post_id
- */
- public function getReposters($post_id){
- return $this->httpReq('get',$this->_baseUrl.'posts/'.urlencode($post_id).'/reposters');
- }
-
- /**
- * Repost an existing Post object.
- * @param integer $post_id The id of the post
- * @return not a clue
- */
- public function repost($post_id){
- return $this->httpReq('post',$this->_baseUrl.'posts/'.urlencode($post_id).'/repost');
- }
-
- /**
- * Delete a post that the user has reposted.
- * @param integer $post_id The id of the post
- * @return not a clue
- */
- public function deleteRepost($post_id){
- return $this->httpReq('delete',$this->_baseUrl.'posts/'.urlencode($post_id).'/repost');
- }
-
- /**
- * List the posts who match a specific search term
- * @param array $params a list of filter, search query, and general Post parameters
- * see: https://developers.app.net/reference/resources/post/search/
- * @param string $query The search query. Supports
- * normal search terms. Searches post text.
- * @return array An array of associative arrays, each representing one post.
- * or false on error
- */
- public function searchPosts($params = array(), $query='', $order='default') {
- if (!is_array($params)) {
- return false;
- }
- if (!empty($query)) {
- $params['query']=$query;
- }
- if ($order=='default') {
- if (!empty($query)) {
- $params['order']='score';
- } else {
- $params['order']='id';
- }
- }
- return $this->httpReq('get',$this->_baseUrl.'posts/search?'.$this->buildQueryString($params));
- }
-
-
- /**
- * List the users who match a specific search term
- * @param string $search The search query. Supports @username or #tag searches as
- * well as normal search terms. Searches username, display name, bio information.
- * Does not search posts.
- * @return array An array of associative arrays, each representing one user.
- */
- public function searchUsers($search="") {
- return $this->httpReq('get',$this->_baseUrl.'users/search?q='.urlencode($search));
- }
-
- /**
- * Return the 20 most recent posts for a stream using a valid Token
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function getTokenStream($params = array()) {
- if ($params['access_token']) {
- return $this->httpReq('get',$this->_baseUrl.'posts/stream?'.$this->buildQueryString($params),$params);
- } else {
- return $this->httpReq('get',$this->_baseUrl.'posts/stream?'.$this->buildQueryString($params));
- }
- }
-
- /**
- * Get a user object by username
- * @param string $name the @name to get
- * @return array representing one user
- */
- public function getUserByName($name=null) {
- return $this->httpReq('get',$this->_baseUrl.'users/@'.$name);
- }
-
- /**
- * Return the 20 most recent Posts from the current User's personalized stream
- * and mentions stream merged into one stream.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: count, before_id, since_id, include_muted, include_deleted,
- * include_directed_posts, and include_annotations.
- * @return An array of associative arrays, each representing a single post.
- */
- public function getUserUnifiedStream($params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'posts/stream/unified?'.$this->buildQueryString($params));
- }
-
- /**
- * Update Profile Data via JSON
- * @data array containing user descriptors
- */
- public function updateUserData($data = array(), $params = array()) {
- $json = json_encode($data);
- return $this->httpReq('put',$this->_baseUrl.'users/me'.'?'.
- $this->buildQueryString($params), $json, 'application/json');
- }
-
- /**
- * Update a user image
- * @which avatar|cover
- * @image path reference to image
- */
- protected function updateUserImage($which = 'avatar', $image = null) {
- $data = array($which=>"@$image");
- return $this->httpReq('post-raw',$this->_baseUrl.'users/me/'.$which, $data, 'multipart/form-data');
- }
-
- public function updateUserAvatar($avatar = null) {
- if($avatar != null)
- return $this->updateUserImage('avatar', $avatar);
- }
-
- public function updateUserCover($cover = null) {
- if($cover != null)
- return $this->updateUserImage('cover', $cover);
- }
-
- /**
- * update stream marker
- */
- public function updateStreamMarker($data = array()) {
- $json = json_encode($data);
- return $this->httpReq('post',$this->_baseUrl.'posts/marker', $json, 'application/json');
- }
-
- /**
- * get a page of current user subscribed channels
- */
- public function getUserSubscriptions($params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'channels?'.$this->buildQueryString($params));
- }
-
- /**
- * get user channels
- */
- public function getMyChannels($params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'channels/me?'.$this->buildQueryString($params));
- }
-
- /**
- * create a channel
- * note: you cannot create a channel with type=net.app.core.pm (see createMessage)
- */
- public function createChannel($data = array()) {
- $json = json_encode($data);
- return $this->httpReq('post',$this->_baseUrl.'channels'.($pm?'/pm/messsages':''), $json, 'application/json');
- }
-
- /**
- * get channelid info
- */
- public function getChannel($channelid, $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'channels/'.$channelid.'?'.$this->buildQueryString($params));
- }
-
- /**
- * get multiple channels' info by an array of channelids
- */
- public function getChannels($channels, $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'channels?ids='.join(',',$channels).'&'.$this->buildQueryString($params));
- }
-
- /**
- * update channelid
- */
- public function updateChannel($channelid, $data = array()) {
- $json = json_encode($data);
- return $this->httpReq('put',$this->_baseUrl.'channels/'.$channelid, $json, 'application/json');
- }
-
- /**
- * subscribe from channelid
- */
- public function channelSubscribe($channelid) {
- return $this->httpReq('post',$this->_baseUrl.'channels/'.$channelid.'/subscribe');
- }
-
- /**
- * unsubscribe from channelid
- */
- public function channelUnsubscribe($channelid) {
- return $this->httpReq('delete',$this->_baseUrl.'channels/'.$channelid.'/subscribe');
- }
-
- /**
- * get all user objects subscribed to channelid
- */
- public function getChannelSubscriptions($channelid, $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'channel/'.$channelid.'/subscribers?'.$this->buildQueryString($params));
- }
-
- /**
- * get all user IDs subscribed to channelid
- */
- public function getChannelSubscriptionsById($channelid) {
- return $this->httpReq('get',$this->_baseUrl.'channel/'.$channelid.'/subscribers/ids');
- }
-
-
- /**
- * get a page of messages in channelid
- */
- public function getMessages($channelid, $params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'channels/'.$channelid.'/messages?'.$this->buildQueryString($params));
- }
-
- /**
- * create message
- * @param $channelid numeric or "pm" for auto-chanenl (type=net.app.core.pm)
- * @param $data array('text'=>'YOUR_MESSAGE') If a type=net.app.core.pm, then "destinations" key can be set to address as an array of people to send this PM too
- */
- public function createMessage($channelid,$data) {
- $json = json_encode($data);
- return $this->httpReq('post',$this->_baseUrl.'channels/'.$channelid.'/messages', $json, 'application/json');
- }
-
- /**
- * get message
- */
- public function getMessage($channelid,$messageid) {
- return $this->httpReq('get',$this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid);
- }
-
- /**
- * delete messsage
- */
- public function deleteMessage($channelid,$messageid) {
- return $this->httpReq('delete',$this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid);
- }
-
-
- /**
- * Get Application Information
- */
- public function getAppTokenInfo() {
- // requires appAccessToken
- if (!$this->_appAccessToken) {
- $this->getAppAccessToken();
- }
- // ensure request is made with our appAccessToken
- $params['access_token']=$this->_appAccessToken;
- return $this->httpReq('get',$this->_baseUrl.'token',$params);
- }
-
- /**
- * Get User Information
- */
- public function getUserTokenInfo() {
- return $this->httpReq('get',$this->_baseUrl.'token');
- }
-
- /**
- * Get Application Authorized User IDs
- */
- public function getAppUserIDs() {
- // requires appAccessToken
- if (!$this->_appAccessToken) {
- $this->getAppAccessToken();
- }
- // ensure request is made with our appAccessToken
- $params['access_token']=$this->_appAccessToken;
- return $this->httpReq('get',$this->_baseUrl.'apps/me/tokens/user_ids',$params);
- }
-
- /**
- * Get Application Authorized User Tokens
- */
- public function getAppUserTokens() {
- // requires appAccessToken
- if (!$this->_appAccessToken) {
- $this->getAppAccessToken();
- }
- // ensure request is made with our appAccessToken
- $params['access_token']=$this->_appAccessToken;
- return $this->httpReq('get',$this->_baseUrl.'apps/me/tokens',$params);
- }
-
- public function getLastRequest() {
- return $this->_last_request;
- }
- public function getLastResponse() {
- return $this->_last_response;
- }
-
- /**
- * Registers your function (or an array of object and method) to be called
- * whenever an event is received via an open app.net stream. Your function
- * will receive a single parameter, which is the object wrapper containing
- * the meta and data.
- * @param mixed A PHP callback (either a string containing the function name,
- * or an array where the first element is the class/object and the second
- * is the method).
- */
- public function registerStreamFunction($function) {
- $this->_streamCallback = $function;
- }
-
- /**
- * Opens a stream that's been created for this user/app and starts sending
- * events/objects to your defined callback functions. You must define at
- * least one callback function before opening a stream.
- * @param mixed $stream Either a stream ID or the endpoint of a stream
- * you've already created. This stream must exist and must be valid for
- * your current access token. If you pass a stream ID, the library will
- * make an API call to get the endpoint.
- *
- * This function will return immediately, but your callback functions
- * will continue to receive events until you call closeStream() or until
- * App.net terminates the stream from their end with an error.
- *
- * If you're disconnected due to a network error, the library will
- * automatically attempt to reconnect you to the same stream, no action
- * on your part is necessary for this. However if the app.net API returns
- * an error, a reconnection attempt will not be made.
- *
- * Note there is no closeStream, because once you open a stream you
- * can't stop it (unless you exit() or die() or throw an uncaught
- * exception, or something else that terminates the script).
- * @return boolean True
- * @see createStream()
- */
- public function openStream($stream) {
- // if there's already a stream running, don't allow another
- if ($this->_currentStream) {
- throw new AppDotNetException('There is already a stream being consumed, only one stream can be consumed per AppDotNetStream instance');
- }
- // must register a callback (or the exercise is pointless)
- if (!$this->_streamCallback) {
- throw new AppDotNetException('You must define your callback function using registerStreamFunction() before calling openStream');
- }
- // if the stream is a numeric value, get the stream info from the api
- if (is_numeric($stream)) {
- $stream = $this->getStream($stream);
- $this->_streamUrl = $stream['endpoint'];
- }
- else {
- $this->_streamUrl = $stream;
- }
- // continue doing this until we get an error back or something...?
- $this->httpStream('get',$this->_streamUrl);
-
- return true;
- }
-
- /**
- * Close the currently open stream.
- * @return true;
- */
- public function closeStream() {
- if (!$this->_lastStreamActivity) {
- // never opened
- return;
- }
- if (!$this->_multiStream) {
- throw new AppDotNetException('You must open a stream before calling closeStream()');
- }
- curl_close($this->_currentStream);
- curl_multi_remove_handle($this->_multiStream,$this->_currentStream);
- curl_multi_close($this->_multiStream);
- $this->_currentStream = null;
- $this->_multiStream = null;
- }
-
- /**
- * Retrieve all streams for the current access token.
- * @return array An array of stream definitions.
- */
- public function getAllStreams() {
- return $this->httpReq('get',$this->_baseUrl.'streams');
- }
-
- /**
- * Returns a single stream specified by a stream ID. The stream must have been
- * created with the current access token.
- * @return array A stream definition
- */
- public function getStream($streamId) {
- return $this->httpReq('get',$this->_baseUrl.'streams/'.urlencode($streamId));
- }
-
- /**
- * Creates a stream for the current app access token.
- *
- * @param array $objectTypes The objects you want to retrieve data for from the
- * stream. At time of writing these can be 'post', 'star', and/or 'user_follow'.
- * If you don't specify, all events will be retrieved.
- */
- public function createStream($objectTypes=null) {
- // default object types to everything
- if (is_null($objectTypes)) {
- $objectTypes = array('post','star','user_follow');
- }
- $data = array(
- 'object_types'=>$objectTypes,
- 'type'=>'long_poll',
- );
- $data = json_encode($data);
- $response = $this->httpReq('post',$this->_baseUrl.'streams',$data,'application/json');
- return $response;
- }
-
- /**
- * Update stream for the current app access token
- *
- * @param integer $streamId The stream ID to update. This stream must have been
- * created by the current access token.
- * @param array $data allows object_types, type, filter_id and key to be updated. filter_id/key can be omitted
- */
- public function updateStream($streamId,$data) {
- // objectTypes is likely required
- if (is_null($data['object_types'])) {
- $data['object_types'] = array('post','star','user_follow');
- }
- // type can still only be long_poll
- if (is_null($data['type'])) {
- $data['type']='long_poll';
- }
- $data = json_encode($data);
- $response = $this->httpReq('put',$this->_baseUrl.'streams/'.urlencode($streamId),$data,'application/json');
- return $response;
- }
-
- /**
- * Deletes a stream if you no longer need it.
- *
- * @param integer $streamId The stream ID to delete. This stream must have been
- * created by the current access token.
- */
- public function deleteStream($streamId) {
- return $this->httpReq('delete',$this->_baseUrl.'streams/'.urlencode($streamId));
- }
-
- /**
- * Deletes all streams created by the current access token.
- */
- public function deleteAllStreams() {
- return $this->httpReq('delete',$this->_baseUrl.'streams');
- }
-
- /**
- * Internal function used to process incoming chunks from the stream. This is only
- * public because it needs to be accessed by CURL. Do not call or use this function
- * in your own code.
- * @ignore
- */
- public function httpStreamReceive($ch,$data) {
- $this->_lastStreamActivity = time();
- $this->_streamBuffer .= $data;
- if (!$this->_streamHeaders) {
- $pos = strpos($this->_streamBuffer,"\r\n\r\n");
- if ($pos!==false) {
- $this->_streamHeaders = substr($this->_streamBuffer,0,$pos);
- $this->_streamBuffer = substr($this->_streamBuffer,$pos+4);
- }
- }
- else {
- $pos = strpos($this->_streamBuffer,"\r\n");
- while ($pos!==false) {
- $command = substr($this->_streamBuffer,0,$pos);
- $this->_streamBuffer = substr($this->_streamBuffer,$pos+2);
- $command = json_decode($command,true);
- if ($command) {
- call_user_func($this->_streamCallback,$command);
- }
- $pos = strpos($this->_streamBuffer,"\r\n");
- }
- }
- return strlen($data);
- }
-
- /**
- * Opens a long lived HTTP connection to the app.net servers, and sends data
- * received to the httpStreamReceive function. As a general rule you should not
- * directly call this method, it's used by openStream().
- */
- protected function httpStream($act, $req, $params=array(),$contentType='application/x-www-form-urlencoded') {
- if ($this->_currentStream) {
- throw new AppDotNetException('There is already an open stream, you must close the existing one before opening a new one');
- }
- $headers = array();
- $this->_streamBuffer = '';
- if ($this->_accessToken) {
- $headers[] = 'Authorization: Bearer '.$this->_accessToken;
- }
- $this->_currentStream = curl_init($req);
- curl_setopt($this->_currentStream, CURLOPT_HTTPHEADER, $headers);
- curl_setopt($this->_currentStream, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($this->_currentStream, CURLINFO_HEADER_OUT, true);
- curl_setopt($this->_currentStream, CURLOPT_HEADER, true);
- if ($this->_sslCA) {
- curl_setopt($this->_currentStream, CURLOPT_CAINFO, $this->_sslCA);
- }
- // every time we receive a chunk of data, forward it to httpStreamReceive
- curl_setopt($this->_currentStream, CURLOPT_WRITEFUNCTION, array($this, "httpStreamReceive"));
-
- // curl_exec($ch);
- // return;
-
- $this->_multiStream = curl_multi_init();
- $this->_lastStreamActivity = time();
- curl_multi_add_handle($this->_multiStream,$this->_currentStream);
- }
-
- public function reconnectStream() {
- $this->closeStream();
- $this->_connectFailCounter++;
- // if we've failed a few times, back off
- if ($this->_connectFailCounter>1) {
- $sleepTime = pow(2,$this->_connectFailCounter);
- // don't sleep more than 60 seconds
- if ($sleepTime>60) {
- $sleepTime = 60;
- }
- sleep($sleepTime);
- }
- $this->httpStream('get',$this->_streamUrl);
- }
-
- /**
- * Process an open stream for x microseconds, then return. This is useful if you want
- * to be doing other things while processing the stream. If you just want to
- * consume the stream without other actions, you can call processForever() instead.
- * @param float @microseconds The number of microseconds to process for before
- * returning. There are 1,000,000 microseconds in a second.
- *
- * @return void
- */
- public function processStream($microseconds=null) {
- if (!$this->_multiStream) {
- throw new AppDotNetException('You must open a stream before calling processStream()');
- }
- $start = microtime(true);
- $active = null;
- $inQueue = null;
- $sleepFor = 0;
- do {
- // if we haven't received anything within 5.5 minutes, reconnect
- // keepalives are sent every 5 minutes (measured on 2013-3-12 by @ryantharp)
- if (time()-$this->_lastStreamActivity>=330) {
- $this->reconnectStream();
- }
- curl_multi_exec($this->_multiStream, $active);
- if (!$active) {
- $httpCode = curl_getinfo($this->_currentStream,CURLINFO_HTTP_CODE);
- // don't reconnect on 400 errors
- if ($httpCode>=400 && $httpCode<=499) {
- throw new AppDotNetException('Received HTTP error '.$httpCode.' check your URL and credentials before reconnecting');
- }
- $this->reconnectStream();
- }
- // sleep for a max of 2/10 of a second
- $timeSoFar = (microtime(true)-$start)*1000000;
- $sleepFor = $this->streamingSleepFor;
- if ($timeSoFar+$sleepFor>$microseconds) {
- $sleepFor = $microseconds - $timeSoFar;
- }
-
- if ($sleepFor>0) {
- usleep($sleepFor);
- }
- } while ($timeSoFar+$sleepFor<$microseconds);
- }
-
- /**
- * Process an open stream forever. This function will never return, if you
- * want to perform other actions while consuming the stream, you should use
- * processFor() instead.
- * @return void This function will never return
- * @see processFor();
- */
- public function processStreamForever() {
- while (true) {
- $this->processStream(600);
- }
- }
-
-
- /**
- * Upload a file to a user's file store
- * @param string $file A string containing the path of the file to upload.
- * @param array $data Additional data about the file you're uploading. At the
- * moment accepted keys are: mime-type, kind, type, name, public and annotations.
- * - If you don't specify mime-type, ADNPHP will attempt to guess the mime type
- * based on the file, however this isn't always reliable.
- * - If you don't specify kind ADNPHP will attempt to determine if the file is
- * an image or not.
- * - If you don't specify name, ADNPHP will use the filename of the first
- * parameter.
- * - If you don't specify public, your file will be uploaded as a private file.
- * - Type is REQUIRED.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: include_annotations|include_file_annotations.
- * @return array An associative array representing the file
- */
- public function createFile($file, $data, $params=array()) {
- if (!$file) {
- throw new AppDotNetException('You must specify a path to a file');
- }
- if (!file_exists($file)) {
- throw new AppDotNetException('File path specified does not exist');
- }
- if (!is_readable($file)) {
- throw new AppDotNetException('File path specified is not readable');
- }
-
- if (!$data) {
- $data = array();
- }
-
- if (!array_key_exists('type',$data) || !$data['type']) {
- throw new AppDotNetException('Type is required when creating a file');
- }
-
- if (!array_key_exists('name',$data)) {
- $data['name'] = basename($file);
- }
-
- if (array_key_exists('mime-type',$data)) {
- $mimeType = $data['mime-type'];
- unset($data['mime-type']);
- }
- else {
- $mimeType = null;
- }
- if (!array_key_exists('kind',$data)) {
- $test = @getimagesize($path);
- if ($test && array_key_exists('mime',$test)) {
- $data['kind'] = 'image';
- if (!$mimeType) {
- $mimeType = $test['mime'];
- }
- }
- else {
- $data['kind'] = 'other';
- }
- }
- if (!$mimeType) {
- $finfo = finfo_open(FILEINFO_MIME_TYPE);
- $mimeType = finfo_file($finfo, $file);
- finfo_close($finfo);
- }
- if (!$mimeType) {
- throw new AppDotNetException('Unable to determine mime type of file, try specifying it explicitly');
- }
- if (!array_key_exists('public',$data) || !$data['public']) {
- $public = false;
- }
- else {
- $public = true;
- }
-
- $data['content'] = "@$file;type=$mimeType";
- return $this->httpReq('post-raw',$this->_baseUrl.'files', $data, 'multipart/form-data');
- }
-
-
- public function createFilePlaceholder($file = null, $params=array()) {
- $name = basename($file);
- $data = array('annotations' => $params['annotations'], 'kind' => $params['kind'],
- 'name' => $name, 'type' => $params['metadata']);
- $json = json_encode($data);
- return $this->httpReq('post',$this->_baseUrl.'files', $json, 'application/json');
- }
-
- public function updateFileContent($fileid, $file) {
-
- $data = file_get_contents($file);
- $finfo = finfo_open(FILEINFO_MIME_TYPE);
- $mime = finfo_file($finfo, $file);
- finfo_close($finfo);
-
- return $this->httpReq('put',$this->_baseUrl.'files/' . $fileid
- .'/content', $data, $mime);
- }
-
- /**
- * Allows for file rename and annotation changes.
- * @param integer $file_id The ID of the file to update
- * @param array $params An associative array of file parameters.
- * @return array An associative array representing the updated file
- */
- public function updateFile($file_id=null, $params=array()) {
- $data = array('annotations' => $params['annotations'] , 'name' => $params['name']);
- $json = json_encode($data);
- return $this->httpReq('put',$this->_baseUrl.'files/'.urlencode($file_id), $json, 'application/json');
- }
-
- /**
- * Returns a specific File.
- * @param integer $file_id The ID of the file to retrieve
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: include_annotations|include_file_annotations.
- * @return array An associative array representing the file
- */
- public function getFile($file_id=null,$params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'files/'.urlencode($file_id)
- .'?'.$this->buildQueryString($params));
- }
-
- public function getFileContent($file_id=null,$params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'files/'.urlencode($file_id)
- .'/content?'.$this->buildQueryString($params));
- }
-
- /** $file_key : derived_file_key */
- public function getDerivedFileContent($file_id=null,$file_key=null,$params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'files/'.urlencode($file_id)
- .'/content/'.urlencode($file_key)
- .'?'.$this->buildQueryString($params));
- }
-
- /**
- * Returns file objects.
- * @param array $file_ids The IDs of the files to retrieve
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: include_annotations|include_file_annotations.
- * @return array An associative array representing the file data.
- */
- public function getFiles($file_ids=array(), $params = array()) {
- $ids = '';
- foreach($file_ids as $id) {
- $ids .= $id . ',';
- }
- $params['ids'] = substr($ids, 0, -1);
- return $this->httpReq('get',$this->_baseUrl.'files'
- .'?'.$this->buildQueryString($params));
- }
-
- /**
- * Returns a user's file objects.
- * @param array $params An associative array of optional general parameters.
- * This will likely change as the API evolves, as of this writing allowed keys
- * are: include_annotations|include_file_annotations|include_user_annotations.
- * @return array An associative array representing the file data.
- */
- public function getUserFiles($params = array()) {
- return $this->httpReq('get',$this->_baseUrl.'users/me/files'
- .'?'.$this->buildQueryString($params));
- }
-
- /**
- * Delete a File. The current user must be the same user who created the File.
- * It returns the deleted File on success.
- * @param integer $file_id The ID of the file to delete
- * @return array An associative array representing the file that was deleted
- */
- public function deleteFile($file_id=null) {
- return $this->httpReq('delete',$this->_baseUrl.'files/'.urlencode($file_id));
- }
+ // The total number of requests you're allowed within the alloted time period
+ private $_rateLimit = null;
+ // The number of requests you have remaining within the alloted time period
+ private $_rateLimitRemaining = null;
+
+ // The number of seconds remaining in the alloted time period
+ private $_rateLimitReset = null;
+
+ // The scope the user has
+ private $_scope = null;
+
+ // token scopes
+ private $_scopes = array();
+
+ // debug info
+ private $_last_request = null;
+ private $_last_response = null;
+
+ // ssl certification
+ private $_sslCA = null;
+
+ // the callback function to be called when an event is received from the stream
+ private $_streamCallback = null;
+
+ // the stream buffer
+ private $_streamBuffer = '';
+
+ // stores the curl handler for the current stream
+ private $_currentStream = null;
+
+ // stores the curl multi handler for the current stream
+ private $_multiStream = null;
+
+ // stores the number of failed connects, so we can back off multiple failures
+ private $_connectFailCounter = 0;
+
+ // stores the most recent stream url, so we can re-connect when needed
+ private $_streamUrl = null;
+
+ // keeps track of the last time we've received a packet from the api, if it's too long we'll reconnect
+ private $_lastStreamActivity = null;
+
+ // stores the headers received when connecting to the stream
+ private $_streamHeaders = null;
+
+ // response meta max_id data
+ private $_maxid = null;
+
+ // response meta min_id data
+ private $_minid = null;
+
+ // response meta more data
+ private $_more = null;
+
+ // response stream marker data
+ private $_last_marker = null;
+
+ // strip envelope response from returned value
+ private $_stripResponseEnvelope = true;
+
+ // if processing stream_markers or any fast stream, decrease $sleepFor
+ public $streamingSleepFor = 20000;
+
+ /**
+ * Constructs an AppDotNet PHP object with the specified client ID and
+ * client secret.
+ *
+ * @param string $client_id The client ID you received from App.net when
+ * creating your app
+ * @param string $client_secret The client secret you received from
+ * App.net when creating your app
+ */
+ public function __construct($client_id, $client_secret)
+ {
+ $this->_clientId = $client_id;
+ $this->_clientSecret = $client_secret;
+
+ // if the digicert certificate exists in the same folder as this file,
+ // remember that fact for later
+ if (file_exists(dirname(__FILE__).'/DigiCertHighAssuranceEVRootCA.pem')) {
+ $this->_sslCA = dirname(__FILE__).'/DigiCertHighAssuranceEVRootCA.pem';
+ }
+ }
+
+ /**
+ * Set whether or not to strip Envelope Response (meta) information
+ * This option will be deprecated in the future. Is it to allow
+ * a stepped migration path between code expecting the old behavior
+ * and new behavior. When not stripped, you still can use the proper
+ * method to pull the meta information. Please start converting your code ASAP.
+ */
+ public function includeResponseEnvelope()
+ {
+ $this->_stripResponseEnvelope = false;
+ }
+
+ /**
+ * Construct the proper Auth URL for the user to visit and either grant
+ * or not access to your app. Usually you would place this as a link for
+ * the user to client, or a redirect to send them to the auth URL.
+ * Also can be called after authentication for additional scopes.
+ *
+ * @param string $callbackUri Where you want the user to be directed
+ * after authenticating with App.net. This must be one of the URIs
+ * allowed by your App.net application settings
+ * @param array $scope An array of scopes (permissions) you wish to obtain
+ * from the user. Currently options are stream, email, write_post, follow,
+ * messages, and export. If you don't specify anything, you'll only receive
+ * access to the user's basic profile (the default)
+ */
+ public function getAuthUrl($callback_uri, $scope = null)
+ {
+
+ // construct an authorization url based on our client id and other data
+ $data = array(
+ 'client_id' => $this->_clientId,
+ 'response_type' => 'code',
+ 'redirect_uri' => $callback_uri,
+ );
+
+ $url = $this->_authUrl;
+ if ($this->_accessToken) {
+ $url .= 'authorize?';
+ } else {
+ $url .= 'authenticate?';
+ }
+ $url .= $this->buildQueryString($data);
+
+ if ($scope) {
+ $url .= '&scope='.implode('+', $scope);
+ }
+
+ // return the constructed url
+ return $url;
+ }
+
+ /**
+ * Call this after they return from the auth page, or anytime you need the
+ * token. For example, you could store it in a database and use
+ * setAccessToken() later on to return on behalf of the user.
+ */
+ public function getAccessToken($callback_uri)
+ {
+ // if there's no access token set, and they're returning from
+ // the auth page with a code, use the code to get a token
+ if (!$this->_accessToken && isset($_GET['code']) && $_GET['code']) {
+
+ // construct the necessary elements to get a token
+ $data = array(
+ 'client_id' => $this->_clientId,
+ 'client_secret' => $this->_clientSecret,
+ 'grant_type' => 'authorization_code',
+ 'redirect_uri' => $callback_uri,
+ 'code' => $_GET['code'],
+ );
+
+ // try and fetch the token with the above data
+ $res = $this->httpReq('post', $this->_authUrl.'access_token', $data);
+
+ // store it for later
+ $this->_accessToken = $res['access_token'];
+ $this->_username = $res['username'];
+ $this->_user_id = $res['user_id'];
+ }
+
+ // return what we have (this may be a token, or it may be nothing)
+ return $this->_accessToken;
+ }
+
+ /**
+ * Check the scope of current token to see if it has required scopes
+ * has to be done after a check.
+ */
+ public function checkScopes($app_scopes)
+ {
+ if (!count($this->_scopes)) {
+ return -1; // _scope is empty
+ }
+ $missing = array();
+ foreach ($app_scopes as $scope) {
+ if (!in_array($scope, $this->_scopes)) {
+ if ($scope == 'public_messages') {
+ // messages works for public_messages
+ if (in_array('messages', $this->_scopes)) {
+ // if we have messages in our scopes
+ continue;
+ }
+ }
+ $missing[] = $scope;
+ }
+ }
+ // identify the ones missing
+ if (count($missing)) {
+ // do something
+ return $missing;
+ }
+
+ return 0; // 0 missing
+ }
+
+ /**
+ * Set the access token (eg: after retrieving it from offline storage).
+ *
+ * @param string $token A valid access token you're previously received
+ * from calling getAccessToken()
+ */
+ public function setAccessToken($token)
+ {
+ $this->_accessToken = $token;
+ }
+
+ /**
+ * Deauthorize the current token (delete your authorization from the API)
+ * Generally this is useful for logging users out from a web app, so they
+ * don't get automatically logged back in the next time you redirect them
+ * to the authorization URL.
+ */
+ public function deauthorizeToken()
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'token');
+ }
+
+ /**
+ * Retrieve an app access token from the app.net API. This allows you
+ * to access the API without going through the user access flow if you
+ * just want to (eg) consume global. App access tokens are required for
+ * some actions (like streaming global). DO NOT share the return value
+ * of this function with any user (or save it in a cookie, etc). This
+ * is considered secret info for your app only.
+ *
+ * @return string The app access token
+ */
+ public function getAppAccessToken()
+ {
+
+ // construct the necessary elements to get a token
+ $data = array(
+ 'client_id' => $this->_clientId,
+ 'client_secret' => $this->_clientSecret,
+ 'grant_type' => 'client_credentials',
+ );
+
+ // try and fetch the token with the above data
+ $res = $this->httpReq('post', $this->_authUrl.'access_token', $data);
+
+ // store it for later
+ $this->_appAccessToken = $res['access_token'];
+ $this->_accessToken = $res['access_token'];
+ $this->_username = null;
+ $this->_user_id = null;
+
+ return $this->_accessToken;
+ }
+
+ /**
+ * Returns the total number of requests you're allowed within the
+ * alloted time period.
+ *
+ * @see getRateLimitReset()
+ */
+ public function getRateLimit()
+ {
+ return $this->_rateLimit;
+ }
+
+ /**
+ * The number of requests you have remaining within the alloted time period.
+ *
+ * @see getRateLimitReset()
+ */
+ public function getRateLimitRemaining()
+ {
+ return $this->_rateLimitRemaining;
+ }
+
+ /**
+ * The number of seconds remaining in the alloted time period.
+ * When this time is up you'll have getRateLimit() available again.
+ */
+ public function getRateLimitReset()
+ {
+ return $this->_rateLimitReset;
+ }
+
+ /**
+ * The scope the user has.
+ */
+ public function getScope()
+ {
+ return $this->_scope;
+ }
+
+ /**
+ * Internal function, parses out important information App.net adds
+ * to the headers.
+ */
+ protected function parseHeaders($response)
+ {
+ // take out the headers
+ // set internal variables
+ // return the body/content
+ $this->_rateLimit = null;
+ $this->_rateLimitRemaining = null;
+ $this->_rateLimitReset = null;
+ $this->_scope = null;
+
+ $response = explode("\r\n\r\n", $response, 2);
+ $headers = $response[0];
+
+ if ($headers == 'HTTP/1.1 100 Continue') {
+ $response = explode("\r\n\r\n", $response[1], 2);
+ $headers = $response[0];
+ }
+
+ if (isset($response[1])) {
+ $content = $response[1];
+ } else {
+ $content = null;
+ }
+
+ // this is not a good way to parse http headers
+ // it will not (for example) take into account multiline headers
+ // but what we're looking for is pretty basic, so we can ignore those shortcomings
+ $headers = explode("\r\n", $headers);
+ foreach ($headers as $header) {
+ $header = explode(': ', $header, 2);
+ if (count($header) < 2) {
+ continue;
+ }
+ list($k, $v) = $header;
+ switch ($k) {
+ case 'X-RateLimit-Remaining':
+ $this->_rateLimitRemaining = $v;
+ break;
+ case 'X-RateLimit-Limit':
+ $this->_rateLimit = $v;
+ break;
+ case 'X-RateLimit-Reset':
+ $this->_rateLimitReset = $v;
+ break;
+ case 'X-OAuth-Scopes':
+ $this->_scope = $v;
+ $this->_scopes = explode(',', $v);
+ break;
+ }
+ }
+
+ return $content;
+ }
+
+ /**
+ * Internal function. Used to turn things like TRUE into 1, and then
+ * calls http_build_query.
+ */
+ protected function buildQueryString($array)
+ {
+ foreach ($array as $k => &$v) {
+ if ($v === true) {
+ $v = '1';
+ } elseif ($v === false) {
+ $v = '0';
+ }
+ unset($v);
+ }
+
+ return http_build_query($array);
+ }
+
+ /**
+ * Internal function to handle all
+ * HTTP requests (POST,PUT,GET,DELETE).
+ */
+ protected function httpReq($act, $req, $params = array(), $contentType = 'application/x-www-form-urlencoded')
+ {
+ $ch = curl_init($req);
+ $headers = array();
+ if ($act != 'get') {
+ curl_setopt($ch, CURLOPT_POST, true);
+ // if they passed an array, build a list of parameters from it
+ if (is_array($params) && $act != 'post-raw') {
+ $params = $this->buildQueryString($params);
+ }
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+ $headers[] = 'Content-Type: '.$contentType;
+ }
+ if ($act != 'post' && $act != 'post-raw') {
+ curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($act));
+ }
+ if ($act == 'get' && isset($params['access_token'])) {
+ $headers[] = 'Authorization: Bearer '.$params['access_token'];
+ } elseif ($this->_accessToken) {
+ $headers[] = 'Authorization: Bearer '.$this->_accessToken;
+ }
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLINFO_HEADER_OUT, true);
+ curl_setopt($ch, CURLOPT_HEADER, true);
+ if ($this->_sslCA) {
+ curl_setopt($ch, CURLOPT_CAINFO, $this->_sslCA);
+ }
+ $this->_last_response = curl_exec($ch);
+ $this->_last_request = curl_getinfo($ch, CURLINFO_HEADER_OUT);
+ $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ curl_close($ch);
+ if ($http_status == 0) {
+ throw new AppDotNetException('Unable to connect to '.$req);
+ }
+ if ($http_status < 200 || $http_status >= 300) {
+ throw new AppDotNetException('HTTP error '.$this->_last_response);
+ }
+ if ($this->_last_request === false) {
+ if (!curl_getinfo($ch, CURLINFO_SSL_VERIFYRESULT)) {
+ throw new AppDotNetException('SSL verification failed, connection terminated.');
+ }
+ }
+ $response = $this->parseHeaders($this->_last_response);
+ $response = json_decode($response, true);
+
+ if (isset($response['meta'])) {
+ if (isset($response['meta']['max_id'])) {
+ $this->_maxid = $response['meta']['max_id'];
+ $this->_minid = $response['meta']['min_id'];
+ }
+ if (isset($response['meta']['more'])) {
+ $this->_more = $response['meta']['more'];
+ }
+ if (isset($response['meta']['marker'])) {
+ $this->_last_marker = $response['meta']['marker'];
+ }
+ }
+
+ // look for errors
+ if (isset($response['error'])) {
+ if (is_array($response['error'])) {
+ throw new AppDotNetException($response['error']['message'],
+ $response['error']['code']);
+ } else {
+ throw new AppDotNetException($response['error']);
+ }
+ }
+
+ // look for response migration errors
+ elseif (isset($response['meta']) && isset($response['meta']['error_message'])) {
+ throw new AppDotNetException($response['meta']['error_message'], $response['meta']['code']);
+ }
+
+ // if we've received a migration response, handle it and return data only
+ elseif ($this->_stripResponseEnvelope && isset($response['meta']) && isset($response['data'])) {
+ return $response['data'];
+ }
+
+ // else non response migration response, just return it
+ else {
+ return $response;
+ }
+ }
+
+ /**
+ * Get max_id from last meta response data envelope.
+ */
+ public function getResponseMaxID()
+ {
+ return $this->_maxid;
+ }
+
+ /**
+ * Get min_id from last meta response data envelope.
+ */
+ public function getResponseMinID()
+ {
+ return $this->_minid;
+ }
+
+ /**
+ * Get more from last meta response data envelope.
+ */
+ public function getResponseMore()
+ {
+ return $this->_more;
+ }
+
+ /**
+ * Get marker from last meta response data envelope.
+ */
+ public function getResponseMarker()
+ {
+ return $this->_last_marker;
+ }
+
+ /**
+ * Fetch API configuration object.
+ */
+ public function getConfig()
+ {
+ return $this->httpReq('get', $this->_baseUrl.'config');
+ }
+
+ /**
+ * Return the Filters for the current user.
+ */
+ public function getAllFilters()
+ {
+ return $this->httpReq('get', $this->_baseUrl.'filters');
+ }
+
+ /**
+ * Create a Filter for the current user.
+ *
+ * @param string $name The name of the new filter
+ * @param array $filters An associative array of filters to be applied.
+ * This may change as the API evolves, as of this writing possible
+ * values are: user_ids, hashtags, link_domains, and mention_user_ids.
+ * You will need to provide at least one filter name=>value pair
+ */
+ public function createFilter($name = 'New filter', $filters = array())
+ {
+ $filters['name'] = $name;
+
+ return $this->httpReq('post', $this->_baseUrl.'filters', $filters);
+ }
+
+ /**
+ * Returns a specific Filter object.
+ *
+ * @param int $filter_id The ID of the filter you wish to retrieve
+ */
+ public function getFilter($filter_id = null)
+ {
+ return $this->httpReq('get', $this->_baseUrl.'filters/'.urlencode($filter_id));
+ }
+
+ /**
+ * Delete a Filter. The Filter must belong to the current User.
+ *
+ * @return object Returns the deleted Filter on success
+ */
+ public function deleteFilter($filter_id = null)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'filters/'.urlencode($filter_id));
+ }
+
+ /**
+ * Process user description, message or post text.
+ * Mentions and hashtags will be parsed out of the
+ * text, as will bare URLs. To create a link in the text without using a
+ * bare URL, include the anchor text in the object text and include a link
+ * entity in the function call.
+ *
+ * @param string $text The text of the description/message/post
+ * @param array $data An associative array of optional post data. This
+ * will likely change as the API evolves, as of this writing allowed keys are:
+ * reply_to, and annotations. "annotations" may be a complex object represented
+ * by an associative array
+ * @param array $params An associative array of optional data to be included
+ * in the URL (such as 'include_annotations' and 'include_machine')
+ *
+ * @return array An associative array representing the post
+ */
+ public function processText($text = null, $data = array(), $params = array())
+ {
+ $data['text'] = $text;
+ $json = json_encode($data);
+ $qs = '';
+ if (!empty($params)) {
+ $qs = '?'.$this->buildQueryString($params);
+ }
+
+ return $this->httpReq('post', $this->_baseUrl.'text/process'.$qs, $json, 'application/json');
+ }
+
+ /**
+ * Create a new Post object. Mentions and hashtags will be parsed out of the
+ * post text, as will bare URLs. To create a link in a post without using a
+ * bare URL, include the anchor text in the post's text and include a link
+ * entity in the post creation call.
+ *
+ * @param string $text The text of the post
+ * @param array $data An associative array of optional post data. This
+ * will likely change as the API evolves, as of this writing allowed keys are:
+ * reply_to, and annotations. "annotations" may be a complex object represented
+ * by an associative array
+ * @param array $params An associative array of optional data to be included
+ * in the URL (such as 'include_annotations' and 'include_machine')
+ *
+ * @return array An associative array representing the post
+ */
+ public function createPost($text = null, $data = array(), $params = array())
+ {
+ $data['text'] = $text;
+
+ $json = json_encode($data);
+ $qs = '';
+ if (!empty($params)) {
+ $qs = '?'.$this->buildQueryString($params);
+ }
+
+ return $this->httpReq('post', $this->_baseUrl.'posts'.$qs, $json, 'application/json');
+ }
+
+ /**
+ * Returns a specific Post.
+ *
+ * @param int $post_id The ID of the post to retrieve
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: include_annotations
+ *
+ * @return array An associative array representing the post
+ */
+ public function getPost($post_id = null, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/'.urlencode($post_id)
+ .'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Delete a Post. The current user must be the same user who created the Post.
+ * It returns the deleted Post on success.
+ *
+ * @param int $post_id The ID of the post to delete
+ * @param array An associative array representing the post that was deleted
+ */
+ public function deletePost($post_id = null)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'posts/'.urlencode($post_id));
+ }
+
+ /**
+ * Retrieve the Posts that are 'in reply to' a specific Post.
+ *
+ * @param int $post_id The ID of the post you want to retrieve replies for
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function getPostReplies($post_id = null, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/'.urlencode($post_id)
+ .'/replies?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Get the most recent Posts created by a specific User in reverse
+ * chronological order (most recent first).
+ *
+ * @param mixed $user_id Either the ID of the user you wish to retrieve posts by,
+ * or the string "me", which will retrieve posts for the user you're authenticated
+ * as
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function getUserPosts($user_id = 'me', $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/'.urlencode($user_id)
+ .'/posts?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Get the most recent Posts mentioning by a specific User in reverse
+ * chronological order (newest first).
+ *
+ * @param mixed $user_id Either the ID of the user who is being mentioned, or
+ * the string "me", which will retrieve posts for the user you're authenticated
+ * as
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function getUserMentions($user_id = 'me', $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/'
+ .urlencode($user_id).'/mentions?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Return the 20 most recent posts from the current User and
+ * the Users they follow.
+ *
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function getUserStream($params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/stream?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Returns a specific user object.
+ *
+ * @param mixed $user_id The ID of the user you want to retrieve, or the string
+ * "me" to retrieve data for the users you're currently authenticated as
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: include_annotations|include_user_annotations
+ *
+ * @return array An associative array representing the user data
+ */
+ public function getUser($user_id = 'me', $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/'.urlencode($user_id)
+ .'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Returns multiple users request by an array of user ids.
+ *
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: include_annotations|include_user_annotations
+ *
+ * @return array An associative array representing the users data
+ */
+ public function getUsers($user_arr, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users?ids='.implode(',', $user_arr)
+ .'&'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Add the specified user ID to the list of users followed.
+ * Returns the User object of the user being followed.
+ *
+ * @param int $user_id The user ID of the user to follow
+ *
+ * @return array An associative array representing the user you just followed
+ */
+ public function followUser($user_id = null)
+ {
+ return $this->httpReq('post', $this->_baseUrl.'users/'.urlencode($user_id).'/follow');
+ }
+
+ /**
+ * Removes the specified user ID to the list of users followed.
+ * Returns the User object of the user being unfollowed.
+ *
+ * @param int $user_id The user ID of the user to unfollow
+ *
+ * @return array An associative array representing the user you just unfollowed
+ */
+ public function unfollowUser($user_id = null)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'users/'.urlencode($user_id).'/follow');
+ }
+
+ /**
+ * Returns an array of User objects the specified user is following.
+ *
+ * @param mixed $user_id Either the ID of the user being followed, or
+ * the string "me", which will retrieve posts for the user you're authenticated
+ * as
+ *
+ * @return array An array of associative arrays, each representing a single
+ * user following $user_id
+ */
+ public function getFollowing($user_id = 'me')
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/'.$user_id.'/following');
+ }
+
+ /**
+ * Returns an array of User objects for users following the specified user.
+ *
+ * @param mixed $user_id Either the ID of the user being followed, or
+ * the string "me", which will retrieve posts for the user you're authenticated
+ * as
+ *
+ * @return array An array of associative arrays, each representing a single
+ * user following $user_id
+ */
+ public function getFollowers($user_id = 'me')
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/'.$user_id.'/followers');
+ }
+
+ /**
+ * Return Posts matching a specific #hashtag.
+ *
+ * @param string $hashtag The hashtag you're looking for
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function searchHashtags($hashtag = null, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/tag/'
+ .urlencode($hashtag).'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Retrieve a list of all public Posts on App.net, often referred to as the
+ * global stream.
+ *
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function getPublicPosts($params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/stream/global?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * List User interactions.
+ */
+ public function getMyInteractions($params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/me/interactions?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Retrieve a user's user ID by specifying their username.
+ * Now supported by the API. We use the API if we have a token
+ * Otherwise we scrape the alpha.app.net site for the info.
+ *
+ * @param string $username The username of the user you want the ID of, without
+ * an @ symbol at the beginning
+ *
+ * @return int The user's user ID
+ */
+ public function getIdByUsername($username = null)
+ {
+ if ($this->_accessToken) {
+ $res = $this->httpReq('get', $this->_baseUrl.'users/@'.$username);
+ $user_id = $res['data']['id'];
+ } else {
+ $ch = curl_init('https://alpha.app.net/'.urlencode(strtolower($username)));
+ curl_setopt($ch, CURLOPT_POST, false);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_USERAGENT,
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:7.0.1) Gecko/20100101 Firefox/7.0.1');
+ $response = curl_exec($ch);
+ curl_close($ch);
+ $temp = explode('title="User Id ', $response);
+ $temp2 = explode('"', $temp[1]);
+ $user_id = $temp2[0];
+ }
+
+ return $user_id;
+ }
+
+ /**
+ * Mute a user.
+ *
+ * @param int $user_id The user ID to mute
+ */
+ public function muteUser($user_id = null)
+ {
+ return $this->httpReq('post', $this->_baseUrl.'users/'.urlencode($user_id).'/mute');
+ }
+
+ /**
+ * Unmute a user.
+ *
+ * @param int $user_id The user ID to unmute
+ */
+ public function unmuteUser($user_id = null)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'users/'.urlencode($user_id).'/mute');
+ }
+
+ /**
+ * List the users muted by the current user.
+ *
+ * @return array An array of associative arrays, each representing one muted user
+ */
+ public function getMuted()
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/me/muted');
+ }
+
+ /**
+ * Star a post.
+ *
+ * @param int $post_id The post ID to star
+ */
+ public function starPost($post_id = null)
+ {
+ return $this->httpReq('post', $this->_baseUrl.'posts/'.urlencode($post_id).'/star');
+ }
+
+ /**
+ * Unstar a post.
+ *
+ * @param int $post_id The post ID to unstar
+ */
+ public function unstarPost($post_id = null)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'posts/'.urlencode($post_id).'/star');
+ }
+
+ /**
+ * List the posts starred by the current user.
+ *
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations.
+ * See https://github.com/appdotnet/api-spec/blob/master/resources/posts.md#general-parameters
+ *
+ * @return array An array of associative arrays, each representing a single
+ * user who has starred a post
+ */
+ public function getStarred($user_id = 'me', $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/'.urlencode($user_id).'/stars'
+ .'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * List the users who have starred a post.
+ *
+ * @param int $post_id the post ID to get stars from
+ *
+ * @return array An array of associative arrays, each representing one user
+ */
+ public function getStars($post_id = null)
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/'.urlencode($post_id).'/stars');
+ }
+
+ /**
+ * Returns an array of User objects of users who reposted the specified post.
+ *
+ * @param int $post_id the post ID to
+ *
+ * @return array An array of associative arrays, each representing a single
+ * user who reposted $post_id
+ */
+ public function getReposters($post_id)
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/'.urlencode($post_id).'/reposters');
+ }
+
+ /**
+ * Repost an existing Post object.
+ *
+ * @param int $post_id The id of the post
+ *
+ * @return not a clue
+ */
+ public function repost($post_id)
+ {
+ return $this->httpReq('post', $this->_baseUrl.'posts/'.urlencode($post_id).'/repost');
+ }
+
+ /**
+ * Delete a post that the user has reposted.
+ *
+ * @param int $post_id The id of the post
+ *
+ * @return not a clue
+ */
+ public function deleteRepost($post_id)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'posts/'.urlencode($post_id).'/repost');
+ }
+
+ /**
+ * List the posts who match a specific search term.
+ *
+ * @param array $params a list of filter, search query, and general Post parameters
+ * see: https://developers.app.net/reference/resources/post/search/
+ * @param string $query The search query. Supports
+ * normal search terms. Searches post text
+ *
+ * @return array An array of associative arrays, each representing one post.
+ * or false on error
+ */
+ public function searchPosts($params = array(), $query = '', $order = 'default')
+ {
+ if (!is_array($params)) {
+ return false;
+ }
+ if (!empty($query)) {
+ $params['query'] = $query;
+ }
+ if ($order == 'default') {
+ if (!empty($query)) {
+ $params['order'] = 'score';
+ } else {
+ $params['order'] = 'id';
+ }
+ }
+
+ return $this->httpReq('get', $this->_baseUrl.'posts/search?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * List the users who match a specific search term.
+ *
+ * @param string $search The search query. Supports @username or #tag searches as
+ * well as normal search terms. Searches username, display name, bio information.
+ * Does not search posts
+ *
+ * @return array An array of associative arrays, each representing one user
+ */
+ public function searchUsers($search = '')
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/search?q='.urlencode($search));
+ }
+
+ /**
+ * Return the 20 most recent posts for a stream using a valid Token.
+ *
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function getTokenStream($params = array())
+ {
+ if ($params['access_token']) {
+ return $this->httpReq('get', $this->_baseUrl.'posts/stream?'.$this->buildQueryString($params), $params);
+ } else {
+ return $this->httpReq('get', $this->_baseUrl.'posts/stream?'.$this->buildQueryString($params));
+ }
+ }
+
+ /**
+ * Get a user object by username.
+ *
+ * @param string $name the @name to get
+ *
+ * @return array representing one user
+ */
+ public function getUserByName($name = null)
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/@'.$name);
+ }
+
+ /**
+ * Return the 20 most recent Posts from the current User's personalized stream
+ * and mentions stream merged into one stream.
+ *
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: count, before_id, since_id, include_muted, include_deleted,
+ * include_directed_posts, and include_annotations
+ *
+ * @return An array of associative arrays, each representing a single post
+ */
+ public function getUserUnifiedStream($params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'posts/stream/unified?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Update Profile Data via JSON.
+ *
+ * @data array containing user descriptors
+ */
+ public function updateUserData($data = array(), $params = array())
+ {
+ $json = json_encode($data);
+
+ return $this->httpReq('put', $this->_baseUrl.'users/me'.'?'.
+ $this->buildQueryString($params), $json, 'application/json');
+ }
+
+ /**
+ * Update a user image.
+ *
+ * @which avatar|cover
+ * @image path reference to image
+ */
+ protected function updateUserImage($which = 'avatar', $image = null)
+ {
+ $data = array($which => "@$image");
+
+ return $this->httpReq('post-raw', $this->_baseUrl.'users/me/'.$which, $data, 'multipart/form-data');
+ }
+
+ public function updateUserAvatar($avatar = null)
+ {
+ if ($avatar != null) {
+ return $this->updateUserImage('avatar', $avatar);
+ }
+ }
+
+ public function updateUserCover($cover = null)
+ {
+ if ($cover != null) {
+ return $this->updateUserImage('cover', $cover);
+ }
+ }
+
+ /**
+ * update stream marker.
+ */
+ public function updateStreamMarker($data = array())
+ {
+ $json = json_encode($data);
+
+ return $this->httpReq('post', $this->_baseUrl.'posts/marker', $json, 'application/json');
+ }
+
+ /**
+ * get a page of current user subscribed channels.
+ */
+ public function getUserSubscriptions($params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channels?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * get user channels.
+ */
+ public function getMyChannels($params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channels/me?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * create a channel
+ * note: you cannot create a channel with type=net.app.core.pm (see createMessage).
+ */
+ public function createChannel($data = array())
+ {
+ $json = json_encode($data);
+
+ return $this->httpReq('post', $this->_baseUrl.'channels'.($pm ? '/pm/messsages' : ''), $json, 'application/json');
+ }
+
+ /**
+ * get channelid info.
+ */
+ public function getChannel($channelid, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channels/'.$channelid.'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * get multiple channels' info by an array of channelids.
+ */
+ public function getChannels($channels, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channels?ids='.implode(',', $channels).'&'.$this->buildQueryString($params));
+ }
+
+ /**
+ * update channelid.
+ */
+ public function updateChannel($channelid, $data = array())
+ {
+ $json = json_encode($data);
+
+ return $this->httpReq('put', $this->_baseUrl.'channels/'.$channelid, $json, 'application/json');
+ }
+
+ /**
+ * subscribe from channelid.
+ */
+ public function channelSubscribe($channelid)
+ {
+ return $this->httpReq('post', $this->_baseUrl.'channels/'.$channelid.'/subscribe');
+ }
+
+ /**
+ * unsubscribe from channelid.
+ */
+ public function channelUnsubscribe($channelid)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'channels/'.$channelid.'/subscribe');
+ }
+
+ /**
+ * get all user objects subscribed to channelid.
+ */
+ public function getChannelSubscriptions($channelid, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channel/'.$channelid.'/subscribers?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * get all user IDs subscribed to channelid.
+ */
+ public function getChannelSubscriptionsById($channelid)
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channel/'.$channelid.'/subscribers/ids');
+ }
+
+ /**
+ * get a page of messages in channelid.
+ */
+ public function getMessages($channelid, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channels/'.$channelid.'/messages?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * create message.
+ *
+ * @param $channelid numeric or "pm" for auto-chanenl (type=net.app.core.pm)
+ * @param $data array('text'=>'YOUR_MESSAGE') If a type=net.app.core.pm, then "destinations" key can be set to address as an array of people to send this PM too
+ */
+ public function createMessage($channelid, $data)
+ {
+ $json = json_encode($data);
+
+ return $this->httpReq('post', $this->_baseUrl.'channels/'.$channelid.'/messages', $json, 'application/json');
+ }
+
+ /**
+ * get message.
+ */
+ public function getMessage($channelid, $messageid)
+ {
+ return $this->httpReq('get', $this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid);
+ }
+
+ /**
+ * delete messsage.
+ */
+ public function deleteMessage($channelid, $messageid)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'channels/'.$channelid.'/messages/'.$messageid);
+ }
+
+ /**
+ * Get Application Information.
+ */
+ public function getAppTokenInfo()
+ {
+ // requires appAccessToken
+ if (!$this->_appAccessToken) {
+ $this->getAppAccessToken();
+ }
+ // ensure request is made with our appAccessToken
+ $params['access_token'] = $this->_appAccessToken;
+
+ return $this->httpReq('get', $this->_baseUrl.'token', $params);
+ }
+
+ /**
+ * Get User Information.
+ */
+ public function getUserTokenInfo()
+ {
+ return $this->httpReq('get', $this->_baseUrl.'token');
+ }
+
+ /**
+ * Get Application Authorized User IDs.
+ */
+ public function getAppUserIDs()
+ {
+ // requires appAccessToken
+ if (!$this->_appAccessToken) {
+ $this->getAppAccessToken();
+ }
+ // ensure request is made with our appAccessToken
+ $params['access_token'] = $this->_appAccessToken;
+
+ return $this->httpReq('get', $this->_baseUrl.'apps/me/tokens/user_ids', $params);
+ }
+
+ /**
+ * Get Application Authorized User Tokens.
+ */
+ public function getAppUserTokens()
+ {
+ // requires appAccessToken
+ if (!$this->_appAccessToken) {
+ $this->getAppAccessToken();
+ }
+ // ensure request is made with our appAccessToken
+ $params['access_token'] = $this->_appAccessToken;
+
+ return $this->httpReq('get', $this->_baseUrl.'apps/me/tokens', $params);
+ }
+
+ public function getLastRequest()
+ {
+ return $this->_last_request;
+ }
+ public function getLastResponse()
+ {
+ return $this->_last_response;
+ }
+
+ /**
+ * Registers your function (or an array of object and method) to be called
+ * whenever an event is received via an open app.net stream. Your function
+ * will receive a single parameter, which is the object wrapper containing
+ * the meta and data.
+ *
+ * @param mixed A PHP callback (either a string containing the function name,
+ * or an array where the first element is the class/object and the second
+ * is the method)
+ */
+ public function registerStreamFunction($function)
+ {
+ $this->_streamCallback = $function;
+ }
+
+ /**
+ * Opens a stream that's been created for this user/app and starts sending
+ * events/objects to your defined callback functions. You must define at
+ * least one callback function before opening a stream.
+ *
+ * @param mixed $stream Either a stream ID or the endpoint of a stream
+ * you've already created. This stream must exist and must be valid for
+ * your current access token. If you pass a stream ID, the library will
+ * make an API call to get the endpoint.
+ *
+ * This function will return immediately, but your callback functions
+ * will continue to receive events until you call closeStream() or until
+ * App.net terminates the stream from their end with an error.
+ *
+ * If you're disconnected due to a network error, the library will
+ * automatically attempt to reconnect you to the same stream, no action
+ * on your part is necessary for this. However if the app.net API returns
+ * an error, a reconnection attempt will not be made.
+ *
+ * Note there is no closeStream, because once you open a stream you
+ * can't stop it (unless you exit() or die() or throw an uncaught
+ * exception, or something else that terminates the script)
+ *
+ * @return bool True
+ *
+ * @see createStream()
+ */
+ public function openStream($stream)
+ {
+ // if there's already a stream running, don't allow another
+ if ($this->_currentStream) {
+ throw new AppDotNetException('There is already a stream being consumed, only one stream can be consumed per AppDotNetStream instance');
+ }
+ // must register a callback (or the exercise is pointless)
+ if (!$this->_streamCallback) {
+ throw new AppDotNetException('You must define your callback function using registerStreamFunction() before calling openStream');
+ }
+ // if the stream is a numeric value, get the stream info from the api
+ if (is_numeric($stream)) {
+ $stream = $this->getStream($stream);
+ $this->_streamUrl = $stream['endpoint'];
+ } else {
+ $this->_streamUrl = $stream;
+ }
+ // continue doing this until we get an error back or something...?
+ $this->httpStream('get', $this->_streamUrl);
+
+ return true;
+ }
+
+ /**
+ * Close the currently open stream.
+ *
+ * @return true;
+ */
+ public function closeStream()
+ {
+ if (!$this->_lastStreamActivity) {
+ // never opened
+ return;
+ }
+ if (!$this->_multiStream) {
+ throw new AppDotNetException('You must open a stream before calling closeStream()');
+ }
+ curl_close($this->_currentStream);
+ curl_multi_remove_handle($this->_multiStream, $this->_currentStream);
+ curl_multi_close($this->_multiStream);
+ $this->_currentStream = null;
+ $this->_multiStream = null;
+ }
+
+ /**
+ * Retrieve all streams for the current access token.
+ *
+ * @return array An array of stream definitions
+ */
+ public function getAllStreams()
+ {
+ return $this->httpReq('get', $this->_baseUrl.'streams');
+ }
+
+ /**
+ * Returns a single stream specified by a stream ID. The stream must have been
+ * created with the current access token.
+ *
+ * @return array A stream definition
+ */
+ public function getStream($streamId)
+ {
+ return $this->httpReq('get', $this->_baseUrl.'streams/'.urlencode($streamId));
+ }
+
+ /**
+ * Creates a stream for the current app access token.
+ *
+ * @param array $objectTypes The objects you want to retrieve data for from the
+ * stream. At time of writing these can be 'post', 'star', and/or 'user_follow'.
+ * If you don't specify, all events will be retrieved
+ */
+ public function createStream($objectTypes = null)
+ {
+ // default object types to everything
+ if (is_null($objectTypes)) {
+ $objectTypes = array('post', 'star', 'user_follow');
+ }
+ $data = array(
+ 'object_types' => $objectTypes,
+ 'type' => 'long_poll',
+ );
+ $data = json_encode($data);
+ $response = $this->httpReq('post', $this->_baseUrl.'streams', $data, 'application/json');
+
+ return $response;
+ }
+
+ /**
+ * Update stream for the current app access token.
+ *
+ * @param int $streamId The stream ID to update. This stream must have been
+ * created by the current access token
+ * @param array $data allows object_types, type, filter_id and key to be updated. filter_id/key can be omitted
+ */
+ public function updateStream($streamId, $data)
+ {
+ // objectTypes is likely required
+ if (is_null($data['object_types'])) {
+ $data['object_types'] = array('post', 'star', 'user_follow');
+ }
+ // type can still only be long_poll
+ if (is_null($data['type'])) {
+ $data['type'] = 'long_poll';
+ }
+ $data = json_encode($data);
+ $response = $this->httpReq('put', $this->_baseUrl.'streams/'.urlencode($streamId), $data, 'application/json');
+
+ return $response;
+ }
+
+ /**
+ * Deletes a stream if you no longer need it.
+ *
+ * @param int $streamId The stream ID to delete. This stream must have been
+ * created by the current access token
+ */
+ public function deleteStream($streamId)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'streams/'.urlencode($streamId));
+ }
+
+ /**
+ * Deletes all streams created by the current access token.
+ */
+ public function deleteAllStreams()
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'streams');
+ }
+
+ /**
+ * Internal function used to process incoming chunks from the stream. This is only
+ * public because it needs to be accessed by CURL. Do not call or use this function
+ * in your own code.
+ *
+ * @ignore
+ */
+ public function httpStreamReceive($ch, $data)
+ {
+ $this->_lastStreamActivity = time();
+ $this->_streamBuffer .= $data;
+ if (!$this->_streamHeaders) {
+ $pos = strpos($this->_streamBuffer, "\r\n\r\n");
+ if ($pos !== false) {
+ $this->_streamHeaders = substr($this->_streamBuffer, 0, $pos);
+ $this->_streamBuffer = substr($this->_streamBuffer, $pos + 4);
+ }
+ } else {
+ $pos = strpos($this->_streamBuffer, "\r\n");
+ while ($pos !== false) {
+ $command = substr($this->_streamBuffer, 0, $pos);
+ $this->_streamBuffer = substr($this->_streamBuffer, $pos + 2);
+ $command = json_decode($command, true);
+ if ($command) {
+ call_user_func($this->_streamCallback, $command);
+ }
+ $pos = strpos($this->_streamBuffer, "\r\n");
+ }
+ }
+
+ return strlen($data);
+ }
+
+ /**
+ * Opens a long lived HTTP connection to the app.net servers, and sends data
+ * received to the httpStreamReceive function. As a general rule you should not
+ * directly call this method, it's used by openStream().
+ */
+ protected function httpStream($act, $req, $params = array(), $contentType = 'application/x-www-form-urlencoded')
+ {
+ if ($this->_currentStream) {
+ throw new AppDotNetException('There is already an open stream, you must close the existing one before opening a new one');
+ }
+ $headers = array();
+ $this->_streamBuffer = '';
+ if ($this->_accessToken) {
+ $headers[] = 'Authorization: Bearer '.$this->_accessToken;
+ }
+ $this->_currentStream = curl_init($req);
+ curl_setopt($this->_currentStream, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($this->_currentStream, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($this->_currentStream, CURLINFO_HEADER_OUT, true);
+ curl_setopt($this->_currentStream, CURLOPT_HEADER, true);
+ if ($this->_sslCA) {
+ curl_setopt($this->_currentStream, CURLOPT_CAINFO, $this->_sslCA);
+ }
+ // every time we receive a chunk of data, forward it to httpStreamReceive
+ curl_setopt($this->_currentStream, CURLOPT_WRITEFUNCTION, array($this, 'httpStreamReceive'));
+
+ // curl_exec($ch);
+ // return;
+
+ $this->_multiStream = curl_multi_init();
+ $this->_lastStreamActivity = time();
+ curl_multi_add_handle($this->_multiStream, $this->_currentStream);
+ }
+
+ public function reconnectStream()
+ {
+ $this->closeStream();
+ ++$this->_connectFailCounter;
+ // if we've failed a few times, back off
+ if ($this->_connectFailCounter > 1) {
+ $sleepTime = pow(2, $this->_connectFailCounter);
+ // don't sleep more than 60 seconds
+ if ($sleepTime > 60) {
+ $sleepTime = 60;
+ }
+ sleep($sleepTime);
+ }
+ $this->httpStream('get', $this->_streamUrl);
+ }
+
+ /**
+ * Process an open stream for x microseconds, then return. This is useful if you want
+ * to be doing other things while processing the stream. If you just want to
+ * consume the stream without other actions, you can call processForever() instead.
+ *
+ * @param float @microseconds The number of microseconds to process for before
+ * returning. There are 1,000,000 microseconds in a second
+ */
+ public function processStream($microseconds = null)
+ {
+ if (!$this->_multiStream) {
+ throw new AppDotNetException('You must open a stream before calling processStream()');
+ }
+ $start = microtime(true);
+ $active = null;
+ $inQueue = null;
+ $sleepFor = 0;
+ do {
+ // if we haven't received anything within 5.5 minutes, reconnect
+ // keepalives are sent every 5 minutes (measured on 2013-3-12 by @ryantharp)
+ if (time() - $this->_lastStreamActivity >= 330) {
+ $this->reconnectStream();
+ }
+ curl_multi_exec($this->_multiStream, $active);
+ if (!$active) {
+ $httpCode = curl_getinfo($this->_currentStream, CURLINFO_HTTP_CODE);
+ // don't reconnect on 400 errors
+ if ($httpCode >= 400 && $httpCode <= 499) {
+ throw new AppDotNetException('Received HTTP error '.$httpCode.' check your URL and credentials before reconnecting');
+ }
+ $this->reconnectStream();
+ }
+ // sleep for a max of 2/10 of a second
+ $timeSoFar = (microtime(true) - $start) * 1000000;
+ $sleepFor = $this->streamingSleepFor;
+ if ($timeSoFar + $sleepFor > $microseconds) {
+ $sleepFor = $microseconds - $timeSoFar;
+ }
+
+ if ($sleepFor > 0) {
+ usleep($sleepFor);
+ }
+ } while ($timeSoFar + $sleepFor < $microseconds);
+ }
+
+ /**
+ * Process an open stream forever. This function will never return, if you
+ * want to perform other actions while consuming the stream, you should use
+ * processFor() instead.
+ *
+ * @see processFor();
+ */
+ public function processStreamForever()
+ {
+ while (true) {
+ $this->processStream(600);
+ }
+ }
+
+ /**
+ * Upload a file to a user's file store.
+ *
+ * @param string $file A string containing the path of the file to upload
+ * @param array $data Additional data about the file you're uploading. At the
+ * moment accepted keys are: mime-type, kind, type, name, public and annotations.
+ * - If you don't specify mime-type, ADNPHP will attempt to guess the mime type
+ * based on the file, however this isn't always reliable.
+ * - If you don't specify kind ADNPHP will attempt to determine if the file is
+ * an image or not.
+ * - If you don't specify name, ADNPHP will use the filename of the first
+ * parameter.
+ * - If you don't specify public, your file will be uploaded as a private file.
+ * - Type is REQUIRED
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: include_annotations|include_file_annotations
+ *
+ * @return array An associative array representing the file
+ */
+ public function createFile($file, $data, $params = array())
+ {
+ if (!$file) {
+ throw new AppDotNetException('You must specify a path to a file');
+ }
+ if (!file_exists($file)) {
+ throw new AppDotNetException('File path specified does not exist');
+ }
+ if (!is_readable($file)) {
+ throw new AppDotNetException('File path specified is not readable');
+ }
+
+ if (!$data) {
+ $data = array();
+ }
+
+ if (!array_key_exists('type', $data) || !$data['type']) {
+ throw new AppDotNetException('Type is required when creating a file');
+ }
+
+ if (!array_key_exists('name', $data)) {
+ $data['name'] = basename($file);
+ }
+
+ if (array_key_exists('mime-type', $data)) {
+ $mimeType = $data['mime-type'];
+ unset($data['mime-type']);
+ } else {
+ $mimeType = null;
+ }
+ if (!array_key_exists('kind', $data)) {
+ $test = @getimagesize($path);
+ if ($test && array_key_exists('mime', $test)) {
+ $data['kind'] = 'image';
+ if (!$mimeType) {
+ $mimeType = $test['mime'];
+ }
+ } else {
+ $data['kind'] = 'other';
+ }
+ }
+ if (!$mimeType) {
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
+ $mimeType = finfo_file($finfo, $file);
+ finfo_close($finfo);
+ }
+ if (!$mimeType) {
+ throw new AppDotNetException('Unable to determine mime type of file, try specifying it explicitly');
+ }
+ if (!array_key_exists('public', $data) || !$data['public']) {
+ $public = false;
+ } else {
+ $public = true;
+ }
+
+ $data['content'] = "@$file;type=$mimeType";
+
+ return $this->httpReq('post-raw', $this->_baseUrl.'files', $data, 'multipart/form-data');
+ }
+
+ public function createFilePlaceholder($file = null, $params = array())
+ {
+ $name = basename($file);
+ $data = array('annotations' => $params['annotations'], 'kind' => $params['kind'],
+ 'name' => $name, 'type' => $params['metadata'], );
+ $json = json_encode($data);
+
+ return $this->httpReq('post', $this->_baseUrl.'files', $json, 'application/json');
+ }
+
+ public function updateFileContent($fileid, $file)
+ {
+ $data = file_get_contents($file);
+ $finfo = finfo_open(FILEINFO_MIME_TYPE);
+ $mime = finfo_file($finfo, $file);
+ finfo_close($finfo);
+
+ return $this->httpReq('put', $this->_baseUrl.'files/'.$fileid
+ .'/content', $data, $mime);
+ }
+
+ /**
+ * Allows for file rename and annotation changes.
+ *
+ * @param int $file_id The ID of the file to update
+ * @param array $params An associative array of file parameters
+ *
+ * @return array An associative array representing the updated file
+ */
+ public function updateFile($file_id = null, $params = array())
+ {
+ $data = array('annotations' => $params['annotations'], 'name' => $params['name']);
+ $json = json_encode($data);
+
+ return $this->httpReq('put', $this->_baseUrl.'files/'.urlencode($file_id), $json, 'application/json');
+ }
+
+ /**
+ * Returns a specific File.
+ *
+ * @param int $file_id The ID of the file to retrieve
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: include_annotations|include_file_annotations
+ *
+ * @return array An associative array representing the file
+ */
+ public function getFile($file_id = null, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'files/'.urlencode($file_id)
+ .'?'.$this->buildQueryString($params));
+ }
+
+ public function getFileContent($file_id = null, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'files/'.urlencode($file_id)
+ .'/content?'.$this->buildQueryString($params));
+ }
+
+ /** $file_key : derived_file_key */
+ public function getDerivedFileContent($file_id = null, $file_key = null, $params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'files/'.urlencode($file_id)
+ .'/content/'.urlencode($file_key)
+ .'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Returns file objects.
+ *
+ * @param array $file_ids The IDs of the files to retrieve
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: include_annotations|include_file_annotations
+ *
+ * @return array An associative array representing the file data
+ */
+ public function getFiles($file_ids = array(), $params = array())
+ {
+ $ids = '';
+ foreach ($file_ids as $id) {
+ $ids .= $id.',';
+ }
+ $params['ids'] = substr($ids, 0, -1);
+
+ return $this->httpReq('get', $this->_baseUrl.'files'
+ .'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Returns a user's file objects.
+ *
+ * @param array $params An associative array of optional general parameters.
+ * This will likely change as the API evolves, as of this writing allowed keys
+ * are: include_annotations|include_file_annotations|include_user_annotations
+ *
+ * @return array An associative array representing the file data
+ */
+ public function getUserFiles($params = array())
+ {
+ return $this->httpReq('get', $this->_baseUrl.'users/me/files'
+ .'?'.$this->buildQueryString($params));
+ }
+
+ /**
+ * Delete a File. The current user must be the same user who created the File.
+ * It returns the deleted File on success.
+ *
+ * @param int $file_id The ID of the file to delete
+ *
+ * @return array An associative array representing the file that was deleted
+ */
+ public function deleteFile($file_id = null)
+ {
+ return $this->httpReq('delete', $this->_baseUrl.'files/'.urlencode($file_id));
+ }
}
-class AppDotNetException extends Exception {}
+class AppDotNetException extends Exception
+{
+}
diff --git a/appnet/appnet.php b/appnet/appnet.php
index 0c53a49f..eedd24e0 100644
--- a/appnet/appnet.php
+++ b/appnet/appnet.php
@@ -4,7 +4,7 @@
* Name: App.net Connector
* Description: Bidirectional (posting and reading) connector for app.net.
* Version: 0.2
- * Author: Michael Vogel
+ * Author: Michael Vogel .
*/
/*
@@ -15,1248 +15,1312 @@
- https://alpha.app.net/opendev/post/34396399 - location data
*/
-require_once('include/enotify.php');
-require_once("include/socgraph.php");
+require_once 'include/enotify.php';
+require_once 'include/socgraph.php';
define('APPNET_DEFAULT_POLL_INTERVAL', 5); // given in minutes
-function appnet_install() {
- register_hook('post_local', 'addon/appnet/appnet.php', 'appnet_post_local');
- register_hook('notifier_normal', 'addon/appnet/appnet.php', 'appnet_send');
- register_hook('jot_networks', 'addon/appnet/appnet.php', 'appnet_jot_nets');
- register_hook('cron', 'addon/appnet/appnet.php', 'appnet_cron');
- register_hook('connector_settings', 'addon/appnet/appnet.php', 'appnet_settings');
- register_hook('connector_settings_post','addon/appnet/appnet.php', 'appnet_settings_post');
- register_hook('prepare_body', 'addon/appnet/appnet.php', 'appnet_prepare_body');
- register_hook('check_item_notification','addon/appnet/appnet.php', 'appnet_check_item_notification');
+function appnet_install()
+{
+ register_hook('post_local', 'addon/appnet/appnet.php', 'appnet_post_local');
+ register_hook('notifier_normal', 'addon/appnet/appnet.php', 'appnet_send');
+ register_hook('jot_networks', 'addon/appnet/appnet.php', 'appnet_jot_nets');
+ register_hook('cron', 'addon/appnet/appnet.php', 'appnet_cron');
+ register_hook('connector_settings', 'addon/appnet/appnet.php', 'appnet_settings');
+ register_hook('connector_settings_post', 'addon/appnet/appnet.php', 'appnet_settings_post');
+ register_hook('prepare_body', 'addon/appnet/appnet.php', 'appnet_prepare_body');
+ register_hook('check_item_notification', 'addon/appnet/appnet.php', 'appnet_check_item_notification');
}
-
-function appnet_uninstall() {
- unregister_hook('post_local', 'addon/appnet/appnet.php', 'appnet_post_local');
- unregister_hook('notifier_normal', 'addon/appnet/appnet.php', 'appnet_send');
- unregister_hook('jot_networks', 'addon/appnet/appnet.php', 'appnet_jot_nets');
- unregister_hook('cron', 'addon/appnet/appnet.php', 'appnet_cron');
- unregister_hook('connector_settings', 'addon/appnet/appnet.php', 'appnet_settings');
- unregister_hook('connector_settings_post', 'addon/appnet/appnet.php', 'appnet_settings_post');
- unregister_hook('prepare_body', 'addon/appnet/appnet.php', 'appnet_prepare_body');
- unregister_hook('check_item_notification','addon/appnet/appnet.php', 'appnet_check_item_notification');
+function appnet_uninstall()
+{
+ unregister_hook('post_local', 'addon/appnet/appnet.php', 'appnet_post_local');
+ unregister_hook('notifier_normal', 'addon/appnet/appnet.php', 'appnet_send');
+ unregister_hook('jot_networks', 'addon/appnet/appnet.php', 'appnet_jot_nets');
+ unregister_hook('cron', 'addon/appnet/appnet.php', 'appnet_cron');
+ unregister_hook('connector_settings', 'addon/appnet/appnet.php', 'appnet_settings');
+ unregister_hook('connector_settings_post', 'addon/appnet/appnet.php', 'appnet_settings_post');
+ unregister_hook('prepare_body', 'addon/appnet/appnet.php', 'appnet_prepare_body');
+ unregister_hook('check_item_notification', 'addon/appnet/appnet.php', 'appnet_check_item_notification');
}
-function appnet_module() {}
-
-function appnet_content(&$a) {
- if(! local_user()) {
- notice( t('Permission denied.') . EOL);
- return '';
- }
-
- require_once("mod/settings.php");
- settings_init($a);
-
- if (isset($a->argv[1]))
- switch ($a->argv[1]) {
- case "connect":
- $o = appnet_connect($a);
- break;
- default:
- $o = print_r($a->argv, true);
- break;
- }
- else
- $o = appnet_connect($a);
-
- return $o;
+function appnet_module()
+{
}
-function appnet_check_item_notification($a, &$notification_data) {
- $own_id = get_pconfig($notification_data["uid"], 'appnet', 'ownid');
+function appnet_content(&$a)
+{
+ if (!local_user()) {
+ notice(t('Permission denied.').EOL);
- $own_user = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
- intval($notification_data["uid"]),
- dbesc("adn::".$own_id)
+ return '';
+ }
+
+ require_once 'mod/settings.php';
+ settings_init($a);
+
+ if (isset($a->argv[1])) {
+ switch ($a->argv[1]) {
+ case 'connect':
+ $o = appnet_connect($a);
+ break;
+ default:
+ $o = print_r($a->argv, true);
+ break;
+ }
+ } else {
+ $o = appnet_connect($a);
+ }
+
+ return $o;
+}
+
+function appnet_check_item_notification($a, &$notification_data)
+{
+ $own_id = get_pconfig($notification_data['uid'], 'appnet', 'ownid');
+
+ $own_user = q("SELECT `url` FROM `contact` WHERE `uid` = %d AND `alias` = '%s' LIMIT 1",
+ intval($notification_data['uid']),
+ dbesc('adn::'.$own_id)
);
- if ($own_user)
- $notification_data["profiles"][] = $own_user[0]["url"];
-}
-
-function appnet_plugin_admin(&$a, &$o){
- $t = get_markup_template( "admin.tpl", "addon/appnet/" );
-
- $o = replace_macros($t, array(
- '$submit' => t('Save Settings'),
- // name, label, value, help, [extra values]
- '$clientid' => array('clientid', t('Client ID'), get_config('appnet', 'clientid' ), ''),
- '$clientsecret' => array('clientsecret', t('Client Secret'), get_config('appnet', 'clientsecret' ), ''),
- ));
-}
-
-function appnet_plugin_admin_post(&$a){
- $clientid = ((x($_POST,'clientid')) ? notags(trim($_POST['clientid'])) : '');
- $clientsecret = ((x($_POST,'clientsecret')) ? notags(trim($_POST['clientsecret'])): '');
- set_config('appnet','clientid',$clientid);
- set_config('appnet','clientsecret',$clientsecret);
- info( t('Settings updated.'). EOL );
-}
-
-function appnet_connect(&$a) {
- require_once 'addon/appnet/AppDotNet.php';
-
- $clientId = get_config('appnet','clientid');
- $clientSecret = get_config('appnet','clientsecret');
-
- if (($clientId == "") OR ($clientSecret == "")) {
- $clientId = get_pconfig(local_user(),'appnet','clientid');
- $clientSecret = get_pconfig(local_user(),'appnet','clientsecret');
- }
-
- $app = new AppDotNet($clientId, $clientSecret);
-
- try {
- $token = $app->getAccessToken($a->get_baseurl().'/appnet/connect');
-
- logger("appnet_connect: authenticated");
- $o .= t("You are now authenticated to app.net. ");
- set_pconfig(local_user(),'appnet','token', $token);
- }
- catch (AppDotNetException $e) {
- $o .= t("
First way: Register an application at https://account.app.net/developer/apps/ and enter Client ID and Client Secret. ');
- $s .= sprintf(t("Use '%s' as Redirect URI
';
- // If it's a repeated message from app.net then do a native repost and exit
- if (appnet_is_repost($a, $b['uid'], $b['body']))
- return;
+ $s .= '
First way: Register an application at https://account.app.net/developer/apps/ and enter Client ID and Client Secret. ');
+ $s .= sprintf(t("Use '%s' as Redirect URI
";
-$a->strings["return to the connector page"] = "návrat ke stránce konektor";
-$a->strings["Post to app.net"] = "Poslat příspěvek na app.net";
-$a->strings["App.net Export"] = "App.net Export";
-$a->strings["Currently connected to: "] = "V současné době připojen k:";
-$a->strings["Enable App.net Post Plugin"] = "Aktivovat App.net Post Plugin";
-$a->strings["Post to App.net by default"] = "Defaultně poslat na App.net";
-$a->strings["Import the remote timeline"] = "Importovat vzdálenou časovou osu";
-$a->strings["
Error fetching user profile. Please clear the configuration and try again.
"] = "
Chyba v přenesení uživatelského profilu. Prosím zkuste smazat konfiguraci a zkusit to znovu.
První možnost: Registrovat svou žádost na https://account.app.net/developer/apps/ a zadat Client ID and Client Secret. ";
+if (!function_exists('string_plural_select_cs')) {
+ function string_plural_select_cs($n)
+ {
+ return ($n == 1) ? 0 : ($n >= 2 && $n <= 4) ? 1 : 2;
+ }
+}
+
+$a->strings['Permission denied.'] = 'Přístup odmítnut.';
+$a->strings['You are now authenticated to app.net. '] = 'Nyní jste přihlášen k app.net.';
+$a->strings['
Error fetching token. Please try again.
'] = '
Chyba v přenesení tokenu. Prosím zkuste to znovu.
';
+$a->strings['return to the connector page'] = 'návrat ke stránce konektor';
+$a->strings['Post to app.net'] = 'Poslat příspěvek na app.net';
+$a->strings['App.net Export'] = 'App.net Export';
+$a->strings['Currently connected to: '] = 'V současné době připojen k:';
+$a->strings['Enable App.net Post Plugin'] = 'Aktivovat App.net Post Plugin';
+$a->strings['Post to App.net by default'] = 'Defaultně poslat na App.net';
+$a->strings['Import the remote timeline'] = 'Importovat vzdálenou časovou osu';
+$a->strings['
Error fetching user profile. Please clear the configuration and try again.
'] = '
Chyba v přenesení uživatelského profilu. Prosím zkuste smazat konfiguraci a zkusit to znovu.
První možnost: Registrovat svou žádost na https://account.app.net/developer/apps/ a zadat Client ID and Client Secret. ';
$a->strings["Use '%s' as Redirect URI
Erster Weg: Registriere eine Anwendung unter https://account.app.net/developer/apps/ und wähle eine Client ID und ein Client Secret.";
+if (!function_exists('string_plural_select_de')) {
+ function string_plural_select_de($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Permission denied.'] = 'Zugriff verweigert.';
+$a->strings['You are now authenticated to app.net. '] = 'Du bist nun auf app.net authentifiziert.';
+$a->strings['
Error fetching token. Please try again.
'] = '
Fehler beim Holen des Tokens, bitte versuche es später noch einmal.
';
+$a->strings['return to the connector page'] = 'zurück zur Connector Seite';
+$a->strings['Post to app.net'] = 'Nach app.net senden';
+$a->strings['App.net Export'] = 'App.net Export';
+$a->strings['Currently connected to: '] = 'Momentan verbunden mit: ';
+$a->strings['Enable App.net Post Plugin'] = 'Veröffentlichungen bei App.net erlauben';
+$a->strings['Post to App.net by default'] = 'Standardmäßig bei App.net veröffentlichen';
+$a->strings['Import the remote timeline'] = 'Importiere die entfernte Zeitleiste';
+$a->strings['
Error fetching user profile. Please clear the configuration and try again.
'] = '
Beim Laden des Nutzerprofils ist ein Fehler aufgetreten. Bitte versuche es später noch einmal.
';
+$a->strings['
You have two ways to connect to App.net.
'] = '
Du hast zwei Wege deinen friendica Account mit App.net zu verbinden.
Erster Weg: Registriere eine Anwendung unter https://account.app.net/developer/apps/ und wähle eine Client ID und ein Client Secret.';
$a->strings["Use '%s' as Redirect URI
Impossible d'obtenir le jeton, merci de réessayer.
";
-$a->strings["return to the connector page"] = "revenir à la page du connecteur";
-$a->strings["Post to app.net"] = "Publier sur app.net";
-$a->strings["App.net Export"] = "Export App.net";
-$a->strings["Currently connected to: "] = "Actuellement connecté à :";
-$a->strings["Enable App.net Post Plugin"] = "Activer le plugin de publication app.net";
-$a->strings["Post to App.net by default"] = "Publier sur App.net par défaut";
-$a->strings["Import the remote timeline"] = "Importer la timeline distante";
-$a->strings["
Error fetching user profile. Please clear the configuration and try again.
"] = "
Impossible d'obtenir le profil utilisateur. Merci de réinitialiser la configuration et de réessayer.
";
-$a->strings["
You have two ways to connect to App.net.
"] = "
Vous avez deux possibilités pour vous connecter à App.net.
Première méthode: Enregistrer une application sur App.net [en] et entrez l'ID Client et le Secret Client. ";
+if (!function_exists('string_plural_select_fr')) {
+ function string_plural_select_fr($n)
+ {
+ return $n > 1;
+ }
+}
+
+$a->strings['Permission denied.'] = 'Autorisation refusée';
+$a->strings['You are now authenticated to app.net. '] = 'Vous êtes maintenant authentifié sur app.net';
+$a->strings['
Error fetching token. Please try again.
'] = "
Impossible d'obtenir le jeton, merci de réessayer.
";
+$a->strings['return to the connector page'] = 'revenir à la page du connecteur';
+$a->strings['Post to app.net'] = 'Publier sur app.net';
+$a->strings['App.net Export'] = 'Export App.net';
+$a->strings['Currently connected to: '] = 'Actuellement connecté à :';
+$a->strings['Enable App.net Post Plugin'] = 'Activer le plugin de publication app.net';
+$a->strings['Post to App.net by default'] = 'Publier sur App.net par défaut';
+$a->strings['Import the remote timeline'] = 'Importer la timeline distante';
+$a->strings['
Error fetching user profile. Please clear the configuration and try again.
'] = "
Impossible d'obtenir le profil utilisateur. Merci de réinitialiser la configuration et de réessayer.
";
+$a->strings['
You have two ways to connect to App.net.
'] = '
Vous avez deux possibilités pour vous connecter à App.net.
Deuxième méthode: obtenez un jeton ur http://dev-lite.jonathonduerig.com/ [en]. ";
-$a->strings["Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.
"] = "Cochez les \"scopes\" suivant: \"Basic\", \"Stream\", \"Write Post\", \"Public Messages\", \"Messages\".";
-$a->strings["Token"] = "Jeton";
-$a->strings["Sign in using App.net"] = "Se connecter avec App.net";
-$a->strings["Clear OAuth configuration"] = "Effacer la configuration OAuth";
-$a->strings["Save Settings"] = "Sauvegarder les paramètres";
+$a->strings['Client ID'] = 'ID Client';
+$a->strings['Client Secret'] = 'Secret Client';
+$a->strings['
Deuxième méthode: obtenez un jeton ur http://dev-lite.jonathonduerig.com/ [en]. ';
+$a->strings["Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.
"] = 'Cochez les "scopes" suivant: "Basic", "Stream", "Write Post", "Public Messages", "Messages".';
+$a->strings['Token'] = 'Jeton';
+$a->strings['Sign in using App.net'] = 'Se connecter avec App.net';
+$a->strings['Clear OAuth configuration'] = 'Effacer la configuration OAuth';
+$a->strings['Save Settings'] = 'Sauvegarder les paramètres';
diff --git a/appnet/lang/it/strings.php b/appnet/lang/it/strings.php
index 01c56524..80d60a65 100644
--- a/appnet/lang/it/strings.php
+++ b/appnet/lang/it/strings.php
@@ -1,29 +1,31 @@
strings["Permission denied."] = "Permesso negato.";
-$a->strings["You are now authenticated to app.net. "] = "Sei autenticato su app.net";
-$a->strings["
Error fetching token. Please try again.
"] = "
Errore recuperando il token. Prova di nuovo
";
-$a->strings["return to the connector page"] = "ritorna alla pagina del connettore";
-$a->strings["Post to app.net"] = "Invia ad app.net";
-$a->strings["App.net Export"] = "Esporta App.net";
-$a->strings["Currently connected to: "] = "Al momento connesso con:";
-$a->strings["Enable App.net Post Plugin"] = "Abilita il plugin di invio ad App.net";
-$a->strings["Post to App.net by default"] = "Invia sempre ad App.net";
-$a->strings["Import the remote timeline"] = "Importa la timeline remota";
-$a->strings["
Error fetching user profile. Please clear the configuration and try again.
"] = "
Errore recuperando il profilo utente. Svuota la configurazione e prova di nuovo.
Registrare un'applicazione su https://account.app.net/developer/apps/ e inserire Client ID e Client Secret.";
+if (!function_exists('string_plural_select_it')) {
+ function string_plural_select_it($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Permission denied.'] = 'Permesso negato.';
+$a->strings['You are now authenticated to app.net. '] = 'Sei autenticato su app.net';
+$a->strings['
Error fetching token. Please try again.
'] = '
Errore recuperando il token. Prova di nuovo
';
+$a->strings['return to the connector page'] = 'ritorna alla pagina del connettore';
+$a->strings['Post to app.net'] = 'Invia ad app.net';
+$a->strings['App.net Export'] = 'Esporta App.net';
+$a->strings['Currently connected to: '] = 'Al momento connesso con:';
+$a->strings['Enable App.net Post Plugin'] = 'Abilita il plugin di invio ad App.net';
+$a->strings['Post to App.net by default'] = 'Invia sempre ad App.net';
+$a->strings['Import the remote timeline'] = 'Importa la timeline remota';
+$a->strings['
Error fetching user profile. Please clear the configuration and try again.
'] = '
Errore recuperando il profilo utente. Svuota la configurazione e prova di nuovo.
Oppure puoi recuperare un token su http://dev-lite.jonathonduerig.com/.';
$a->strings["Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.
"] = "Imposta gli ambiti 'Basic', 'Stream', 'Scrivi Post', 'Messaggi Pubblici', 'Messaggi'.";
-$a->strings["Token"] = "Token";
-$a->strings["Sign in using App.net"] = "Autenticati con App.net";
-$a->strings["Clear OAuth configuration"] = "Pulisci configurazione OAuth";
-$a->strings["Save Settings"] = "Salva Impostazioni";
+$a->strings['Token'] = 'Token';
+$a->strings['Sign in using App.net'] = 'Autenticati con App.net';
+$a->strings['Clear OAuth configuration'] = 'Pulisci configurazione OAuth';
+$a->strings['Save Settings'] = 'Salva Impostazioni';
diff --git a/appnet/lang/nl/strings.php b/appnet/lang/nl/strings.php
index ba72e364..72e93981 100644
--- a/appnet/lang/nl/strings.php
+++ b/appnet/lang/nl/strings.php
@@ -1,29 +1,31 @@
strings["Permission denied."] = "Toegang geweigerd";
-$a->strings["You are now authenticated to app.net. "] = "Je bent nu aangemeld bij app.net.";
-$a->strings["
Error fetching token. Please try again.
"] = "
Fout tijdens token fetching. Probeer het nogmaals.
";
-$a->strings["return to the connector page"] = "ga terug naar de connector pagina";
-$a->strings["Post to app.net"] = "Post naar app.net.";
-$a->strings["App.net Export"] = "App.net Export";
-$a->strings["Currently connected to: "] = "Momenteel verbonden met:";
-$a->strings["Enable App.net Post Plugin"] = "App.net Post Plugin inschakelen";
-$a->strings["Post to App.net by default"] = "Naar App.net posten als standaard instellen";
-$a->strings["Import the remote timeline"] = "The tijdlijn op afstand importeren";
-$a->strings["
Error fetching user profile. Please clear the configuration and try again.
"] = "
Fout tijdens het ophalen van gebruikersprofiel. Leeg de configuratie en probeer het opnieuw.
";
-$a->strings["
You have two ways to connect to App.net.
"] = "
Er zijn twee manieren om met App.net te verbinden.
";
-$a->strings["
First way: Register an application at https://account.app.net/developer/apps/ and enter Client ID and Client Secret. "] = "";
-$a->strings["Use '%s' as Redirect URI
Second way: fetch a token at http://dev-lite.jonathonduerig.com/. "] = "";
-$a->strings["Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.
"] = "";
-$a->strings["Token"] = "";
-$a->strings["Sign in using App.net"] = "";
-$a->strings["Clear OAuth configuration"] = "";
-$a->strings["Save Settings"] = "";
+if (!function_exists('string_plural_select_nl')) {
+ function string_plural_select_nl($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Permission denied.'] = 'Toegang geweigerd';
+$a->strings['You are now authenticated to app.net. '] = 'Je bent nu aangemeld bij app.net.';
+$a->strings['
Error fetching token. Please try again.
'] = '
Fout tijdens token fetching. Probeer het nogmaals.
';
+$a->strings['return to the connector page'] = 'ga terug naar de connector pagina';
+$a->strings['Post to app.net'] = 'Post naar app.net.';
+$a->strings['App.net Export'] = 'App.net Export';
+$a->strings['Currently connected to: '] = 'Momenteel verbonden met:';
+$a->strings['Enable App.net Post Plugin'] = 'App.net Post Plugin inschakelen';
+$a->strings['Post to App.net by default'] = 'Naar App.net posten als standaard instellen';
+$a->strings['Import the remote timeline'] = 'The tijdlijn op afstand importeren';
+$a->strings['
Error fetching user profile. Please clear the configuration and try again.
'] = '
Fout tijdens het ophalen van gebruikersprofiel. Leeg de configuratie en probeer het opnieuw.
';
+$a->strings['
You have two ways to connect to App.net.
'] = '
Er zijn twee manieren om met App.net te verbinden.
';
+$a->strings['
First way: Register an application at https://account.app.net/developer/apps/ and enter Client ID and Client Secret. '] = '';
+$a->strings["Use '%s' as Redirect URI
Second way: fetch a token at http://dev-lite.jonathonduerig.com/. '] = '';
+$a->strings["Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.
"] = '';
+$a->strings['Token'] = '';
+$a->strings['Sign in using App.net'] = '';
+$a->strings['Clear OAuth configuration'] = '';
+$a->strings['Save Settings'] = '';
diff --git a/appnet/lang/pt-br/strings.php b/appnet/lang/pt-br/strings.php
index b8e1112c..0e30abe2 100644
--- a/appnet/lang/pt-br/strings.php
+++ b/appnet/lang/pt-br/strings.php
@@ -1,29 +1,31 @@
1);;
-}}
-;
-$a->strings["Permission denied."] = "Permissão negada.";
-$a->strings["You are now authenticated to app.net. "] = "Você está autenticado no app.net.";
-$a->strings["
Error fetching token. Please try again.
"] = "Erro ocorrido na obtenção do token. Tente novamente.";
-$a->strings["return to the connector page"] = "Volte a página de conectores.";
-$a->strings["Post to app.net"] = "Publicar no App.net";
-$a->strings["App.net Export"] = "App.net exportar";
-$a->strings["Currently connected to: "] = "Atualmente conectado em: ";
-$a->strings["Enable App.net Post Plugin"] = "Habilitar plug-in para publicar no App.net";
-$a->strings["Post to App.net by default"] = "Publicar em App.net por padrão";
-$a->strings["Import the remote timeline"] = "Importar a linha do tempo remota";
-$a->strings["
Error fetching user profile. Please clear the configuration and try again.
"] = "Erro na obtenção do perfil do usuário. Confira as configurações e tente novamente.";
-$a->strings["
1º Método: Registre uma aplicação em https://account.app.net/developer/apps/ e entre o Client ID e Client Secret";
+if (!function_exists('string_plural_select_pt_br')) {
+ function string_plural_select_pt_br($n)
+ {
+ return $n > 1;
+ }
+}
+
+$a->strings['Permission denied.'] = 'Permissão negada.';
+$a->strings['You are now authenticated to app.net. '] = 'Você está autenticado no app.net.';
+$a->strings['
Error fetching token. Please try again.
'] = 'Erro ocorrido na obtenção do token. Tente novamente.';
+$a->strings['return to the connector page'] = 'Volte a página de conectores.';
+$a->strings['Post to app.net'] = 'Publicar no App.net';
+$a->strings['App.net Export'] = 'App.net exportar';
+$a->strings['Currently connected to: '] = 'Atualmente conectado em: ';
+$a->strings['Enable App.net Post Plugin'] = 'Habilitar plug-in para publicar no App.net';
+$a->strings['Post to App.net by default'] = 'Publicar em App.net por padrão';
+$a->strings['Import the remote timeline'] = 'Importar a linha do tempo remota';
+$a->strings['
Error fetching user profile. Please clear the configuration and try again.
'] = 'Erro na obtenção do perfil do usuário. Confira as configurações e tente novamente.';
+$a->strings['
2º Método: obtenha um token em http://dev-lite.jonathonduerig.com/. ';
$a->strings["Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.
"] = "Adicione valor as estas saídas: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.";
-$a->strings["Token"] = "Token";
-$a->strings["Sign in using App.net"] = "Entre usando o App.net";
-$a->strings["Clear OAuth configuration"] = "Limpar configuração OAuth";
-$a->strings["Save Settings"] = "Salvar Configurações";
+$a->strings['Token'] = 'Token';
+$a->strings['Sign in using App.net'] = 'Entre usando o App.net';
+$a->strings['Clear OAuth configuration'] = 'Limpar configuração OAuth';
+$a->strings['Save Settings'] = 'Salvar Configurações';
diff --git a/appnet/lang/ro/strings.php b/appnet/lang/ro/strings.php
index fa8d139d..61da05e1 100644
--- a/appnet/lang/ro/strings.php
+++ b/appnet/lang/ro/strings.php
@@ -1,29 +1,31 @@
19)||(($n%100==0)&&($n!=0)))?2:1));;
-}}
-;
-$a->strings["Permission denied."] = "Permisiune refuzată.";
-$a->strings["You are now authenticated to app.net. "] = "Acum sunteți autentificat pe App.net.";
-$a->strings["
Error fetching token. Please try again.
"] = "
Eroare la procesarea token-ului. Vă rugăm să reîncercați.
";
-$a->strings["return to the connector page"] = "revenire la pagina de conectare";
-$a->strings["Post to app.net"] = "Postați pe App.net";
-$a->strings["App.net Export"] = "Exportare pe App.net";
-$a->strings["Currently connected to: "] = "Conectat curent la:";
-$a->strings["Enable App.net Post Plugin"] = "Activare Modul Postare pe App.net";
-$a->strings["Post to App.net by default"] = "Postați implicit pe App.net";
-$a->strings["Import the remote timeline"] = "Importare cronologie la distanță";
-$a->strings["
Error fetching user profile. Please clear the configuration and try again.
"] = "
Eroare la procesarea profilului de utilizator. Vă rugăm să ștergeți configurarea şi apoi reîncercați.
Prima modalitate: Înregistrați o cerere pe https://account.app.net/developer/apps/ şi introduceți ID Client şi Cheia Secretă Client.";
+if (!function_exists('string_plural_select_ro')) {
+ function string_plural_select_ro($n)
+ {
+ return $n == 1 ? 0 : ((($n % 100 > 19) || (($n % 100 == 0) && ($n != 0))) ? 2 : 1);
+ }
+}
+
+$a->strings['Permission denied.'] = 'Permisiune refuzată.';
+$a->strings['You are now authenticated to app.net. '] = 'Acum sunteți autentificat pe App.net.';
+$a->strings['
Error fetching token. Please try again.
'] = '
Eroare la procesarea token-ului. Vă rugăm să reîncercați.
';
+$a->strings['return to the connector page'] = 'revenire la pagina de conectare';
+$a->strings['Post to app.net'] = 'Postați pe App.net';
+$a->strings['App.net Export'] = 'Exportare pe App.net';
+$a->strings['Currently connected to: '] = 'Conectat curent la:';
+$a->strings['Enable App.net Post Plugin'] = 'Activare Modul Postare pe App.net';
+$a->strings['Post to App.net by default'] = 'Postați implicit pe App.net';
+$a->strings['Import the remote timeline'] = 'Importare cronologie la distanță';
+$a->strings['
Error fetching user profile. Please clear the configuration and try again.
'] = '
Eroare la procesarea profilului de utilizator. Vă rugăm să ștergeți configurarea şi apoi reîncercați.
Prima modalitate: Înregistrați o cerere pe https://account.app.net/developer/apps/ şi introduceți ID Client şi Cheia Secretă Client.';
$a->strings["Use '%s' as Redirect URI
A doua cale: autorizați un indicativ de acces token de pe http://dev-lite.jonathonduerig.com/ .";
+$a->strings['Client ID'] = 'ID Client';
+$a->strings['Client Secret'] = 'Cheia Secretă Client';
+$a->strings['
A doua cale: autorizați un indicativ de acces token de pe http://dev-lite.jonathonduerig.com/ .';
$a->strings["Set these scopes: 'Basic', 'Stream', 'Write Post', 'Public Messages', 'Messages'.
"] = "Stabiliți aceste scopuri: 'De Bază', 'Flux', 'Scriere Postare', 'Mesaje Publice', 'Mesaje'.";
-$a->strings["Token"] = "Token";
-$a->strings["Sign in using App.net"] = "Autentificați-vă utilizând App.net";
-$a->strings["Clear OAuth configuration"] = "Ștergeți configurările OAuth";
-$a->strings["Save Settings"] = "Salvare Configurări";
+$a->strings['Token'] = 'Token';
+$a->strings['Sign in using App.net'] = 'Autentificați-vă utilizând App.net';
+$a->strings['Clear OAuth configuration'] = 'Ștergeți configurările OAuth';
+$a->strings['Save Settings'] = 'Salvare Configurări';
diff --git a/blackout/blackout.php b/blackout/blackout.php
index 3678969e..e4c270f8 100644
--- a/blackout/blackout.php
+++ b/blackout/blackout.php
@@ -4,7 +4,7 @@
* Description: Blackout your ~friendica node during a given period, requires PHP >= 5.3
* License: MIT
* Version: 1.0
- * Author: Tobias Diekershoff
+ * Author: Tobias Diekershoff .
*
* About
* =====
@@ -36,10 +36,10 @@
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
- *
+ *
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
- *
+ *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -48,73 +48,83 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-
-
-function blackout_install() {
+function blackout_install()
+{
register_hook('page_header', 'addon/blackout/blackout.php', 'blackout_redirect');
}
-function blackout_uninstall() {
+function blackout_uninstall()
+{
unregister_hook('page_header', 'addon/blackout/blackout.php', 'blackout_redirect');
}
-function blackout_redirect ($a, $b) {
+function blackout_redirect($a, $b)
+{
// if we have a logged in user, don't throw her out
if (local_user()) {
return true;
}
- if (! (version_compare(PHP_VERSION, '5.3.0') >= 0))
- return true;
+ if (!(version_compare(PHP_VERSION, '5.3.0') >= 0)) {
+ return true;
+ }
// else...
- $mystart = get_config('blackout','begindate');
- $myend = get_config('blackout','enddate');
- $myurl = get_config('blackout','url');
+ $mystart = get_config('blackout', 'begindate');
+ $myend = get_config('blackout', 'enddate');
+ $myurl = get_config('blackout', 'url');
$now = time();
$date1 = DateTime::createFromFormat('Y-m-d G:i', $mystart);
$date2 = DateTime::createFromFormat('Y-m-d G:i', $myend);
- if ( $date1 && $date2 ) {
+ if ($date1 && $date2) {
$date1 = DateTime::createFromFormat('Y-m-d G:i', $mystart)->format('U');
$date2 = DateTime::createFromFormat('Y-m-d G:i', $myend)->format('U');
} else {
- $date1 = 0;
- $date2 = 0;
+ $date1 = 0;
+ $date2 = 0;
}
- if (( $date1 <= $now ) && ( $now <= $date2 )) {
+ if (($date1 <= $now) && ($now <= $date2)) {
logger('redirecting user to blackout page');
goaway($myurl);
}
}
-function blackout_plugin_admin(&$a, &$o) {
- $mystart = get_config('blackout','begindate');
- if (! is_string($mystart)) { $mystart = "YYYY-MM-DD:hhmm"; }
- $myend = get_config('blackout','enddate');
- if (! is_string($myend)) { $myend = "YYYY-MM-DD:hhmm"; }
- $myurl = get_config('blackout','url');
- if (! is_string($myurl)) { $myurl = "http://www.example.com"; }
- $t = get_markup_template( "admin.tpl", "addon/blackout/" );
-
- $o = replace_macros($t, array(
+function blackout_plugin_admin(&$a, &$o)
+{
+ $mystart = get_config('blackout', 'begindate');
+ if (!is_string($mystart)) {
+ $mystart = 'YYYY-MM-DD:hhmm';
+ }
+ $myend = get_config('blackout', 'enddate');
+ if (!is_string($myend)) {
+ $myend = 'YYYY-MM-DD:hhmm';
+ }
+ $myurl = get_config('blackout', 'url');
+ if (!is_string($myurl)) {
+ $myurl = 'http://www.example.com';
+ }
+ $t = get_markup_template('admin.tpl', 'addon/blackout/');
+
+ $o = replace_macros($t, array(
'$submit' => t('Save Settings'),
- '$rurl' => array("rurl", "Redirect URL", $myurl, "all your visitors from the web will be redirected to this URL"),
- '$startdate' => array("startdate", "Begin of the Blackout (YYYY-MM-DD hh:mm)", $mystart, "format is YYYY year, MM month, DD day, hh hour and mm minute"),
- '$enddate' => array("enddate", "End of the Blackout (YYYY-MM-DD hh:mm)", $myend, ""),
+ '$rurl' => array('rurl', 'Redirect URL', $myurl, 'all your visitors from the web will be redirected to this URL'),
+ '$startdate' => array('startdate', 'Begin of the Blackout (YYYY-MM-DD hh:mm)', $mystart, 'format is YYYY year, MM month, DD day, hh hour and mm minute'),
+ '$enddate' => array('enddate', 'End of the Blackout (YYYY-MM-DD hh:mm)', $myend, ''),
));
$date1 = DateTime::createFromFormat('Y-m-d G:i', $mystart);
$date2 = DateTime::createFromFormat('Y-m-d G:i', $myend);
if ($date2 < $date1) {
- $o = "
The end-date is prior to the start-date of the blackout, you should fix this.
" . $o;
+ $o = "
The end-date is prior to the start-date of the blackout, you should fix this.
".$o;
} else {
- $o = '
Please double check that the current settings for the blackout. Begin will be '.$mystart.' and it will end '.$myend.'.
' . $o;
+ $o = '
Please double check that the current settings for the blackout. Begin will be '.$mystart.' and it will end '.$myend.'.
'.$o;
}
}
-function blackout_plugin_admin_post (&$a) {
+function blackout_plugin_admin_post(&$a)
+{
$begindate = trim($_POST['startdate']);
$enddate = trim($_POST['enddate']);
$url = trim($_POST['rurl']);
- set_config('blackout','begindate',$begindate);
- set_config('blackout','enddate',$enddate);
- set_config('blackout','url',$url);
+ set_config('blackout', 'begindate', $begindate);
+ set_config('blackout', 'enddate', $enddate);
+ set_config('blackout', 'url', $url);
}
diff --git a/blackout/lang/ca/strings.php b/blackout/lang/ca/strings.php
index 87481b12..aad6b1a8 100644
--- a/blackout/lang/ca/strings.php
+++ b/blackout/lang/ca/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Enviar";
+strings['Submit'] = 'Enviar';
diff --git a/blackout/lang/cs/strings.php b/blackout/lang/cs/strings.php
index 6bca0c65..09fa368d 100644
--- a/blackout/lang/cs/strings.php
+++ b/blackout/lang/cs/strings.php
@@ -1,14 +1,16 @@
=2 && $n<=4) ? 1 : 2;;
-}}
-;
-$a->strings["Save Settings"] = "Uložit Nastavení";
-$a->strings["Redirect URL"] = "URL Přesměrování";
-$a->strings["all your visitors from the web will be redirected to this URL"] = "všichni vaši návštěvníci z webu budou přesměrování na tuto URL adresu";
-$a->strings["Begin of the Blackout"] = "Zahájení odstávky";
-$a->strings["format is YYYY year, MM month, DD day, hh hour and mm minute"] = "formát je RRRR rok, MM měsíc, DD den, hh hodina a mm minuta";
-$a->strings["End of the Blackout"] = "Konec odstávky";
-$a->strings["The end-date is prior to the start-date of the blackout, you should fix this."] = "Datum konce odstávky je před datem zahájení odstávky prosím opravte to.";
+if (!function_exists('string_plural_select_cs')) {
+ function string_plural_select_cs($n)
+ {
+ return ($n == 1) ? 0 : ($n >= 2 && $n <= 4) ? 1 : 2;
+ }
+}
+
+$a->strings['Save Settings'] = 'Uložit Nastavení';
+$a->strings['Redirect URL'] = 'URL Přesměrování';
+$a->strings['all your visitors from the web will be redirected to this URL'] = 'všichni vaši návštěvníci z webu budou přesměrování na tuto URL adresu';
+$a->strings['Begin of the Blackout'] = 'Zahájení odstávky';
+$a->strings['format is YYYY year, MM month, DD day, hh hour and mm minute'] = 'formát je RRRR rok, MM měsíc, DD den, hh hodina a mm minuta';
+$a->strings['End of the Blackout'] = 'Konec odstávky';
+$a->strings['The end-date is prior to the start-date of the blackout, you should fix this.'] = 'Datum konce odstávky je před datem zahájení odstávky prosím opravte to.';
diff --git a/blackout/lang/de/strings.php b/blackout/lang/de/strings.php
index 66570090..7d65336e 100644
--- a/blackout/lang/de/strings.php
+++ b/blackout/lang/de/strings.php
@@ -1,14 +1,16 @@
strings["Save Settings"] = "Einstellungen speichern";
-$a->strings["Redirect URL"] = "Umleitungs-URL";
-$a->strings["all your visitors from the web will be redirected to this URL"] = "Alle Besucher der Webseite werden zu dieser URL umgeleitet";
-$a->strings["Begin of the Blackout"] = "Beginn des Blackouts";
-$a->strings["format is YYYY year, MM month, DD day, hh hour and mm minute"] = "Das Format ist YYYY Jahr, MM Monat, DD Tag, hh Stunde und mm Minute";
-$a->strings["End of the Blackout"] = "Ende des Blackouts";
-$a->strings["The end-date is prior to the start-date of the blackout, you should fix this."] = "Das Enddatum liegt vor dem Startdatum des Blackouts, du solltest dies korrigieren.";
+if (!function_exists('string_plural_select_de')) {
+ function string_plural_select_de($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Save Settings'] = 'Einstellungen speichern';
+$a->strings['Redirect URL'] = 'Umleitungs-URL';
+$a->strings['all your visitors from the web will be redirected to this URL'] = 'Alle Besucher der Webseite werden zu dieser URL umgeleitet';
+$a->strings['Begin of the Blackout'] = 'Beginn des Blackouts';
+$a->strings['format is YYYY year, MM month, DD day, hh hour and mm minute'] = 'Das Format ist YYYY Jahr, MM Monat, DD Tag, hh Stunde und mm Minute';
+$a->strings['End of the Blackout'] = 'Ende des Blackouts';
+$a->strings['The end-date is prior to the start-date of the blackout, you should fix this.'] = 'Das Enddatum liegt vor dem Startdatum des Blackouts, du solltest dies korrigieren.';
diff --git a/blackout/lang/eo/strings.php b/blackout/lang/eo/strings.php
index 68b5936b..36bcddc6 100644
--- a/blackout/lang/eo/strings.php
+++ b/blackout/lang/eo/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Sendi";
+strings['Submit'] = 'Sendi';
diff --git a/blackout/lang/es/strings.php b/blackout/lang/es/strings.php
index 867a8c9b..f88853e7 100644
--- a/blackout/lang/es/strings.php
+++ b/blackout/lang/es/strings.php
@@ -1,14 +1,16 @@
strings["Save Settings"] = "Guardar configuración";
-$a->strings["Redirect URL"] = "Redirigir URL";
-$a->strings["all your visitors from the web will be redirected to this URL"] = "todos los visitantes de la web serán redirigidos a esta dirección.";
-$a->strings["Begin of the Blackout"] = "Inicio del apagón.";
-$a->strings["format is YYYY year, MM month, DD day, hh hour and mm minute"] = "formato es YYYY año, MM mes, DD día, hh hora y mm minuto";
-$a->strings["End of the Blackout"] = "Fin del apagón.";
-$a->strings["The end-date is prior to the start-date of the blackout, you should fix this."] = "La fecha de final del apagón es antes de la fecha de inicio, deberías arreglar esto.";
+if (!function_exists('string_plural_select_es')) {
+ function string_plural_select_es($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Save Settings'] = 'Guardar configuración';
+$a->strings['Redirect URL'] = 'Redirigir URL';
+$a->strings['all your visitors from the web will be redirected to this URL'] = 'todos los visitantes de la web serán redirigidos a esta dirección.';
+$a->strings['Begin of the Blackout'] = 'Inicio del apagón.';
+$a->strings['format is YYYY year, MM month, DD day, hh hour and mm minute'] = 'formato es YYYY año, MM mes, DD día, hh hora y mm minuto';
+$a->strings['End of the Blackout'] = 'Fin del apagón.';
+$a->strings['The end-date is prior to the start-date of the blackout, you should fix this.'] = 'La fecha de final del apagón es antes de la fecha de inicio, deberías arreglar esto.';
diff --git a/blackout/lang/fr/strings.php b/blackout/lang/fr/strings.php
index ce184038..f240c433 100644
--- a/blackout/lang/fr/strings.php
+++ b/blackout/lang/fr/strings.php
@@ -1,14 +1,16 @@
1);;
-}}
-;
-$a->strings["Save Settings"] = "Sauvegarder les paramètres";
-$a->strings["Redirect URL"] = "Adresse de redirection";
-$a->strings["all your visitors from the web will be redirected to this URL"] = "Tous vos visiteurs venant du web seront redirigés vers cette URL.";
-$a->strings["Begin of the Blackout"] = "Début du blackout";
-$a->strings["format is YYYY year, MM month, DD day, hh hour and mm minute"] = "Le format est YYYY année, MM mois, DD jour, hh heure and mm minute";
-$a->strings["End of the Blackout"] = "Fin du blackout";
-$a->strings["The end-date is prior to the start-date of the blackout, you should fix this."] = "La date de fin est antérieure à la date de début. Veuillez corriger cela.";
+if (!function_exists('string_plural_select_fr')) {
+ function string_plural_select_fr($n)
+ {
+ return $n > 1;
+ }
+}
+
+$a->strings['Save Settings'] = 'Sauvegarder les paramètres';
+$a->strings['Redirect URL'] = 'Adresse de redirection';
+$a->strings['all your visitors from the web will be redirected to this URL'] = 'Tous vos visiteurs venant du web seront redirigés vers cette URL.';
+$a->strings['Begin of the Blackout'] = 'Début du blackout';
+$a->strings['format is YYYY year, MM month, DD day, hh hour and mm minute'] = 'Le format est YYYY année, MM mois, DD jour, hh heure and mm minute';
+$a->strings['End of the Blackout'] = 'Fin du blackout';
+$a->strings['The end-date is prior to the start-date of the blackout, you should fix this.'] = 'La date de fin est antérieure à la date de début. Veuillez corriger cela.';
diff --git a/blackout/lang/is/strings.php b/blackout/lang/is/strings.php
index 94f89330..1bae877d 100644
--- a/blackout/lang/is/strings.php
+++ b/blackout/lang/is/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Senda inn";
+strings['Submit'] = 'Senda inn';
diff --git a/blackout/lang/it/strings.php b/blackout/lang/it/strings.php
index b0142236..32665f99 100644
--- a/blackout/lang/it/strings.php
+++ b/blackout/lang/it/strings.php
@@ -1,14 +1,16 @@
strings["Save Settings"] = "Salva Impostazioni";
-$a->strings["Redirect URL"] = "URL di reindirizzamento";
-$a->strings["all your visitors from the web will be redirected to this URL"] = "tutti i visitatori dal web verranno reindirizzati a questo URL";
-$a->strings["Begin of the Blackout"] = "Inzio del blackout";
-$a->strings["format is YYYY year, MM month, DD day, hh hour and mm minute"] = "il formato è YYYY anno, MM mese, DD giorno, hh ora e mm minuto";
-$a->strings["End of the Blackout"] = "Fine del blackout";
-$a->strings["The end-date is prior to the start-date of the blackout, you should fix this."] = "La data di fine è precedente alla data di inizio. Dovresti sistemarla.";
+if (!function_exists('string_plural_select_it')) {
+ function string_plural_select_it($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Save Settings'] = 'Salva Impostazioni';
+$a->strings['Redirect URL'] = 'URL di reindirizzamento';
+$a->strings['all your visitors from the web will be redirected to this URL'] = 'tutti i visitatori dal web verranno reindirizzati a questo URL';
+$a->strings['Begin of the Blackout'] = 'Inzio del blackout';
+$a->strings['format is YYYY year, MM month, DD day, hh hour and mm minute'] = 'il formato è YYYY anno, MM mese, DD giorno, hh ora e mm minuto';
+$a->strings['End of the Blackout'] = 'Fine del blackout';
+$a->strings['The end-date is prior to the start-date of the blackout, you should fix this.'] = 'La data di fine è precedente alla data di inizio. Dovresti sistemarla.';
diff --git a/blackout/lang/nb-no/strings.php b/blackout/lang/nb-no/strings.php
index 9001ec4a..6aca03bd 100644
--- a/blackout/lang/nb-no/strings.php
+++ b/blackout/lang/nb-no/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Lagre";
+strings['Submit'] = 'Lagre';
diff --git a/blackout/lang/pl/strings.php b/blackout/lang/pl/strings.php
index e18a64fb..96360b86 100644
--- a/blackout/lang/pl/strings.php
+++ b/blackout/lang/pl/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Potwierdź";
+strings['Submit'] = 'Potwierdź';
diff --git a/blackout/lang/pt-br/strings.php b/blackout/lang/pt-br/strings.php
index 87481b12..aad6b1a8 100644
--- a/blackout/lang/pt-br/strings.php
+++ b/blackout/lang/pt-br/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Enviar";
+strings['Submit'] = 'Enviar';
diff --git a/blackout/lang/ro/strings.php b/blackout/lang/ro/strings.php
index 498f7c3e..2e46c970 100644
--- a/blackout/lang/ro/strings.php
+++ b/blackout/lang/ro/strings.php
@@ -1,14 +1,16 @@
19)||(($n%100==0)&&($n!=0)))?2:1));;
-}}
-;
-$a->strings["Save Settings"] = "Salvare Configurări";
-$a->strings["Redirect URL"] = "URL de Redirecționare";
-$a->strings["all your visitors from the web will be redirected to this URL"] = "toți vizitatorii dvs. de pe web vor fi redirecționați către acest URL";
-$a->strings["Begin of the Blackout"] = "Pornire punct Blackout";
-$a->strings["format is YYYY year, MM month, DD day, hh hour and mm minute"] = "formatul este YYYY anul, MM luna, DD ziua, hh ora și mm minute";
-$a->strings["End of the Blackout"] = "Finalizare punct Blackout";
-$a->strings["The end-date is prior to the start-date of the blackout, you should fix this."] = "Data de finalizare este anterioară punctului blackout de pornire, ar trebui să corectați aceasta.";
+if (!function_exists('string_plural_select_ro')) {
+ function string_plural_select_ro($n)
+ {
+ return $n == 1 ? 0 : ((($n % 100 > 19) || (($n % 100 == 0) && ($n != 0))) ? 2 : 1);
+ }
+}
+
+$a->strings['Save Settings'] = 'Salvare Configurări';
+$a->strings['Redirect URL'] = 'URL de Redirecționare';
+$a->strings['all your visitors from the web will be redirected to this URL'] = 'toți vizitatorii dvs. de pe web vor fi redirecționați către acest URL';
+$a->strings['Begin of the Blackout'] = 'Pornire punct Blackout';
+$a->strings['format is YYYY year, MM month, DD day, hh hour and mm minute'] = 'formatul este YYYY anul, MM luna, DD ziua, hh ora și mm minute';
+$a->strings['End of the Blackout'] = 'Finalizare punct Blackout';
+$a->strings['The end-date is prior to the start-date of the blackout, you should fix this.'] = 'Data de finalizare este anterioară punctului blackout de pornire, ar trebui să corectați aceasta.';
diff --git a/blackout/lang/ru/strings.php b/blackout/lang/ru/strings.php
index ab5e2246..f100be77 100644
--- a/blackout/lang/ru/strings.php
+++ b/blackout/lang/ru/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Подтвердить";
+strings['Submit'] = 'Подтвердить';
diff --git a/blackout/lang/sv/strings.php b/blackout/lang/sv/strings.php
index 3ec569a7..4575a404 100644
--- a/blackout/lang/sv/strings.php
+++ b/blackout/lang/sv/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Spara";
+strings['Submit'] = 'Spara';
diff --git a/blackout/lang/zh-cn/strings.php b/blackout/lang/zh-cn/strings.php
index d6d8e7d2..241eef3d 100644
--- a/blackout/lang/zh-cn/strings.php
+++ b/blackout/lang/zh-cn/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "提交";
+strings['Submit'] = '提交';
diff --git a/blockem/blockem.php b/blockem/blockem.php
index 223a1990..7801745c 100755
--- a/blockem/blockem.php
+++ b/blockem/blockem.php
@@ -5,161 +5,155 @@
* Name: blockem
* Description: block people
* Version: 1.0
- * Author: Mike Macgirvin
- *
+ * Author: Mike Macgirvin .
*/
-
-function blockem_install() {
- register_hook('prepare_body', 'addon/blockem/blockem.php', 'blockem_prepare_body');
- register_hook('display_item', 'addon/blockem/blockem.php', 'blockem_display_item');
- register_hook('plugin_settings', 'addon/blockem/blockem.php', 'blockem_addon_settings');
- register_hook('plugin_settings_post', 'addon/blockem/blockem.php', 'blockem_addon_settings_post');
- register_hook('conversation_start', 'addon/blockem/blockem.php', 'blockem_conversation_start');
- register_hook('item_photo_menu', 'addon/blockem/blockem.php', 'blockem_item_photo_menu');
- register_hook('enotify_store', 'addon/blockem/blockem.php', 'blockem_enotify_store' );
+function blockem_install()
+{
+ register_hook('prepare_body', 'addon/blockem/blockem.php', 'blockem_prepare_body');
+ register_hook('display_item', 'addon/blockem/blockem.php', 'blockem_display_item');
+ register_hook('plugin_settings', 'addon/blockem/blockem.php', 'blockem_addon_settings');
+ register_hook('plugin_settings_post', 'addon/blockem/blockem.php', 'blockem_addon_settings_post');
+ register_hook('conversation_start', 'addon/blockem/blockem.php', 'blockem_conversation_start');
+ register_hook('item_photo_menu', 'addon/blockem/blockem.php', 'blockem_item_photo_menu');
+ register_hook('enotify_store', 'addon/blockem/blockem.php', 'blockem_enotify_store');
}
-
-function blockem_uninstall() {
- unregister_hook('prepare_body', 'addon/blockem/blockem.php', 'blockem_prepare_body');
- unregister_hook('display_item', 'addon/blockem/blockem.php', 'blockem_display_item');
- unregister_hook('plugin_settings', 'addon/blockem/blockem.php', 'blockem_addon_settings');
- unregister_hook('plugin_settings_post', 'addon/blockem/blockem.php', 'blockem_addon_settings_post');
- unregister_hook('conversation_start', 'addon/blockem/blockem.php', 'blockem_conversation_start');
- unregister_hook('item_photo_menu', 'addon/blockem/blockem.php', 'blockem_item_photo_menu');
- unregister_hook('enotify_store', 'addon/blockem/blockem.php', 'blockem_enotify_store' );
-
+function blockem_uninstall()
+{
+ unregister_hook('prepare_body', 'addon/blockem/blockem.php', 'blockem_prepare_body');
+ unregister_hook('display_item', 'addon/blockem/blockem.php', 'blockem_display_item');
+ unregister_hook('plugin_settings', 'addon/blockem/blockem.php', 'blockem_addon_settings');
+ unregister_hook('plugin_settings_post', 'addon/blockem/blockem.php', 'blockem_addon_settings_post');
+ unregister_hook('conversation_start', 'addon/blockem/blockem.php', 'blockem_conversation_start');
+ unregister_hook('item_photo_menu', 'addon/blockem/blockem.php', 'blockem_item_photo_menu');
+ unregister_hook('enotify_store', 'addon/blockem/blockem.php', 'blockem_enotify_store');
}
-
-
-
-
-function blockem_addon_settings(&$a,&$s) {
-
- if(! local_user())
- return;
+function blockem_addon_settings(&$a, &$s)
+{
+ if (!local_user()) {
+ return;
+ }
/* Add our stylesheet to the page so we can make our settings look nice */
- $a->page['htmlhead'] .= '' . "\r\n";
+ $a->page['htmlhead'] .= ''."\r\n";
-
- $words = get_pconfig(local_user(),'blockem','words');
- if(! $words)
- $words = '';
+ $words = get_pconfig(local_user(), 'blockem', 'words');
+ if (!$words) {
+ $words = '';
+ }
$s .= '';
- $s .= '
';
-
+ $s .= '';
}
-
-function blogger_settings_post(&$a,&$b) {
-
- if(x($_POST,'blogger-submit')) {
-
- set_pconfig(local_user(),'blogger','post',intval($_POST['blogger']));
- set_pconfig(local_user(),'blogger','post_by_default',intval($_POST['bl_bydefault']));
- set_pconfig(local_user(),'blogger','bl_username',trim($_POST['bl_username']));
- set_pconfig(local_user(),'blogger','bl_password',trim($_POST['bl_password']));
- set_pconfig(local_user(),'blogger','bl_blog',trim($_POST['bl_blog']));
-
- }
-
+function blogger_settings_post(&$a, &$b)
+{
+ if (x($_POST, 'blogger-submit')) {
+ set_pconfig(local_user(), 'blogger', 'post', intval($_POST['blogger']));
+ set_pconfig(local_user(), 'blogger', 'post_by_default', intval($_POST['bl_bydefault']));
+ set_pconfig(local_user(), 'blogger', 'bl_username', trim($_POST['bl_username']));
+ set_pconfig(local_user(), 'blogger', 'bl_password', trim($_POST['bl_password']));
+ set_pconfig(local_user(), 'blogger', 'bl_blog', trim($_POST['bl_blog']));
+ }
}
-function blogger_post_local(&$a,&$b) {
+function blogger_post_local(&$a, &$b)
+{
- // This can probably be changed to allow editing by pointing to a different API endpoint
+ // This can probably be changed to allow editing by pointing to a different API endpoint
- if($b['edit'])
- return;
+ if ($b['edit']) {
+ return;
+ }
- if((! local_user()) || (local_user() != $b['uid']))
- return;
+ if ((!local_user()) || (local_user() != $b['uid'])) {
+ return;
+ }
- if($b['private'] || $b['parent'])
- return;
+ if ($b['private'] || $b['parent']) {
+ return;
+ }
- $bl_post = intval(get_pconfig(local_user(),'blogger','post'));
+ $bl_post = intval(get_pconfig(local_user(), 'blogger', 'post'));
- $bl_enable = (($bl_post && x($_REQUEST,'blogger_enable')) ? intval($_REQUEST['blogger_enable']) : 0);
+ $bl_enable = (($bl_post && x($_REQUEST, 'blogger_enable')) ? intval($_REQUEST['blogger_enable']) : 0);
- if($_REQUEST['api_source'] && intval(get_pconfig(local_user(),'blogger','post_by_default')))
- $bl_enable = 1;
+ if ($_REQUEST['api_source'] && intval(get_pconfig(local_user(), 'blogger', 'post_by_default'))) {
+ $bl_enable = 1;
+ }
- if(! $bl_enable)
- return;
+ if (!$bl_enable) {
+ return;
+ }
- if(strlen($b['postopts']))
- $b['postopts'] .= ',';
- $b['postopts'] .= 'blogger';
+ if (strlen($b['postopts'])) {
+ $b['postopts'] .= ',';
+ }
+ $b['postopts'] .= 'blogger';
}
-
-
-
-function blogger_send(&$a,&$b) {
-
- if($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited']))
+function blogger_send(&$a, &$b)
+{
+ if ($b['deleted'] || $b['private'] || ($b['created'] !== $b['edited'])) {
return;
+ }
- if(! strstr($b['postopts'],'blogger'))
+ if (!strstr($b['postopts'], 'blogger')) {
return;
+ }
- if($b['parent'] != $b['id'])
+ if ($b['parent'] != $b['id']) {
return;
+ }
+ $bl_username = xmlify(get_pconfig($b['uid'], 'blogger', 'bl_username'));
+ $bl_password = xmlify(get_pconfig($b['uid'], 'blogger', 'bl_password'));
+ $bl_blog = get_pconfig($b['uid'], 'blogger', 'bl_blog');
- $bl_username = xmlify(get_pconfig($b['uid'],'blogger','bl_username'));
- $bl_password = xmlify(get_pconfig($b['uid'],'blogger','bl_password'));
- $bl_blog = get_pconfig($b['uid'],'blogger','bl_blog');
+ if ($bl_username && $bl_password && $bl_blog) {
+ require_once 'include/bbcode.php';
- if($bl_username && $bl_password && $bl_blog) {
+ $title = ''.(($b['title']) ? $b['title'] : t('Post from Friendica')).'';
+ $post = $title.bbcode($b['body']);
+ $post = xmlify($post);
- require_once('include/bbcode.php');
-
- $title = '' . (($b['title']) ? $b['title'] : t('Post from Friendica')) . '';
- $post = $title . bbcode($b['body']);
- $post = xmlify($post);
-
- $xml = <<< EOT
+ $xml = <<< EOT
blogger.newPost
@@ -195,12 +193,11 @@ function blogger_send(&$a,&$b) {
EOT;
- logger('blogger: data: ' . $xml, LOGGER_DATA);
+ logger('blogger: data: '.$xml, LOGGER_DATA);
- if($bl_blog !== 'test')
- $x = post_url($bl_blog,$xml);
- logger('posted to blogger: ' . (($x) ? $x : ''), LOGGER_DEBUG);
-
- }
+ if ($bl_blog !== 'test') {
+ $x = post_url($bl_blog, $xml);
+ }
+ logger('posted to blogger: '.(($x) ? $x : ''), LOGGER_DEBUG);
+ }
}
-
diff --git a/blogger/lang/ca/strings.php b/blogger/lang/ca/strings.php
index 354d354a..a89b2f26 100644
--- a/blogger/lang/ca/strings.php
+++ b/blogger/lang/ca/strings.php
@@ -1,11 +1,11 @@
-strings["Post to blogger"] = "Enviament a blogger";
-$a->strings["Blogger Post Settings"] = "Ajustos d'enviament a blogger";
-$a->strings["Enable Blogger Post Plugin"] = "Habilita el Plugin d'Enviaments a Blogger";
-$a->strings["Blogger username"] = "Nom d'usuari a blogger";
-$a->strings["Blogger password"] = "Contrasenya a blogger";
-$a->strings["Blogger API URL"] = "Blogger API URL";
-$a->strings["Post to Blogger by default"] = "Enviament a Blogger per defecte";
-$a->strings["Submit"] = "Enviar";
-$a->strings["Post from Friendica"] = "Enviament des de Friendica";
+strings['Post to blogger'] = 'Enviament a blogger';
+$a->strings['Blogger Post Settings'] = "Ajustos d'enviament a blogger";
+$a->strings['Enable Blogger Post Plugin'] = "Habilita el Plugin d'Enviaments a Blogger";
+$a->strings['Blogger username'] = "Nom d'usuari a blogger";
+$a->strings['Blogger password'] = 'Contrasenya a blogger';
+$a->strings['Blogger API URL'] = 'Blogger API URL';
+$a->strings['Post to Blogger by default'] = 'Enviament a Blogger per defecte';
+$a->strings['Submit'] = 'Enviar';
+$a->strings['Post from Friendica'] = 'Enviament des de Friendica';
diff --git a/blogger/lang/de/strings.php b/blogger/lang/de/strings.php
index 8e44b4c2..9fff4e10 100644
--- a/blogger/lang/de/strings.php
+++ b/blogger/lang/de/strings.php
@@ -1,16 +1,18 @@
strings["Post to blogger"] = "Auf Blogger posten";
-$a->strings["Blogger Export"] = "Blogger Export";
-$a->strings["Enable Blogger Post Plugin"] = "Blogger-Post-Plugin aktivieren";
-$a->strings["Blogger username"] = "Blogger-Benutzername";
-$a->strings["Blogger password"] = "Blogger-Passwort";
-$a->strings["Blogger API URL"] = "Blogger-API-URL";
-$a->strings["Post to Blogger by default"] = "Standardmäßig auf Blogger posten";
-$a->strings["Save Settings"] = "Einstellungen speichern";
-$a->strings["Post from Friendica"] = "Post via Friendica";
+if (!function_exists('string_plural_select_de')) {
+ function string_plural_select_de($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Post to blogger'] = 'Auf Blogger posten';
+$a->strings['Blogger Export'] = 'Blogger Export';
+$a->strings['Enable Blogger Post Plugin'] = 'Blogger-Post-Plugin aktivieren';
+$a->strings['Blogger username'] = 'Blogger-Benutzername';
+$a->strings['Blogger password'] = 'Blogger-Passwort';
+$a->strings['Blogger API URL'] = 'Blogger-API-URL';
+$a->strings['Post to Blogger by default'] = 'Standardmäßig auf Blogger posten';
+$a->strings['Save Settings'] = 'Einstellungen speichern';
+$a->strings['Post from Friendica'] = 'Post via Friendica';
diff --git a/blogger/lang/eo/strings.php b/blogger/lang/eo/strings.php
index 5ab29790..5c145dae 100644
--- a/blogger/lang/eo/strings.php
+++ b/blogger/lang/eo/strings.php
@@ -1,11 +1,11 @@
-strings["Post to blogger"] = "Afiŝi al blogger";
-$a->strings["Blogger Post Settings"] = "Agordo pri Blogger Afiŝoj";
-$a->strings["Enable Blogger Post Plugin"] = "Ŝalti la Blogger afiŝo kromprogramon";
-$a->strings["Blogger username"] = "Blogger uzantonomo";
-$a->strings["Blogger password"] = "Blogger pasvorto";
-$a->strings["Blogger API URL"] = "Blogger API URL";
-$a->strings["Post to Blogger by default"] = "Defaŭlte afiŝi al Blogger";
-$a->strings["Submit"] = "Sendi";
-$a->strings["Post from Friendica"] = "Afiŝo de Friendica";
+strings['Post to blogger'] = 'Afiŝi al blogger';
+$a->strings['Blogger Post Settings'] = 'Agordo pri Blogger Afiŝoj';
+$a->strings['Enable Blogger Post Plugin'] = 'Ŝalti la Blogger afiŝo kromprogramon';
+$a->strings['Blogger username'] = 'Blogger uzantonomo';
+$a->strings['Blogger password'] = 'Blogger pasvorto';
+$a->strings['Blogger API URL'] = 'Blogger API URL';
+$a->strings['Post to Blogger by default'] = 'Defaŭlte afiŝi al Blogger';
+$a->strings['Submit'] = 'Sendi';
+$a->strings['Post from Friendica'] = 'Afiŝo de Friendica';
diff --git a/blogger/lang/es/strings.php b/blogger/lang/es/strings.php
index 3ef963d9..80025d31 100644
--- a/blogger/lang/es/strings.php
+++ b/blogger/lang/es/strings.php
@@ -1,11 +1,11 @@
-strings["Post to blogger"] = "Publícar en Blogger";
-$a->strings["Blogger Post Settings"] = "Configuración de las publicaciones en Blogger";
-$a->strings["Enable Blogger Post Plugin"] = "Activar el módulo de publicación en Blogger";
-$a->strings["Blogger username"] = "Nombre de usuario de Blogger";
-$a->strings["Blogger password"] = "Contraseña de Blogger";
-$a->strings["Blogger API URL"] = "Dirección de la API de Blogger";
-$a->strings["Post to Blogger by default"] = "Publicar en Blogger por defecto";
-$a->strings["Submit"] = "Envíar";
-$a->strings["Post from Friendica"] = "Publicado desde Friendica";
+strings['Post to blogger'] = 'Publícar en Blogger';
+$a->strings['Blogger Post Settings'] = 'Configuración de las publicaciones en Blogger';
+$a->strings['Enable Blogger Post Plugin'] = 'Activar el módulo de publicación en Blogger';
+$a->strings['Blogger username'] = 'Nombre de usuario de Blogger';
+$a->strings['Blogger password'] = 'Contraseña de Blogger';
+$a->strings['Blogger API URL'] = 'Dirección de la API de Blogger';
+$a->strings['Post to Blogger by default'] = 'Publicar en Blogger por defecto';
+$a->strings['Submit'] = 'Envíar';
+$a->strings['Post from Friendica'] = 'Publicado desde Friendica';
diff --git a/blogger/lang/fr/strings.php b/blogger/lang/fr/strings.php
index 2265182a..df7fee71 100644
--- a/blogger/lang/fr/strings.php
+++ b/blogger/lang/fr/strings.php
@@ -1,16 +1,18 @@
1);;
-}}
-;
-$a->strings["Post to blogger"] = "Poster sur Blogger";
-$a->strings["Blogger Export"] = "";
-$a->strings["Enable Blogger Post Plugin"] = "Activer le connecteur Blogger";
-$a->strings["Blogger username"] = "Nom d'utilisateur Blogger";
-$a->strings["Blogger password"] = "Mot de passe Blogger";
-$a->strings["Blogger API URL"] = "URL de l'API de Blogger";
-$a->strings["Post to Blogger by default"] = "";
-$a->strings["Save Settings"] = "Sauvegarder les paramètres";
-$a->strings["Post from Friendica"] = "";
+if (!function_exists('string_plural_select_fr')) {
+ function string_plural_select_fr($n)
+ {
+ return $n > 1;
+ }
+}
+
+$a->strings['Post to blogger'] = 'Poster sur Blogger';
+$a->strings['Blogger Export'] = '';
+$a->strings['Enable Blogger Post Plugin'] = 'Activer le connecteur Blogger';
+$a->strings['Blogger username'] = "Nom d'utilisateur Blogger";
+$a->strings['Blogger password'] = 'Mot de passe Blogger';
+$a->strings['Blogger API URL'] = "URL de l'API de Blogger";
+$a->strings['Post to Blogger by default'] = '';
+$a->strings['Save Settings'] = 'Sauvegarder les paramètres';
+$a->strings['Post from Friendica'] = '';
diff --git a/blogger/lang/is/strings.php b/blogger/lang/is/strings.php
index 01f532f6..c5ab6464 100644
--- a/blogger/lang/is/strings.php
+++ b/blogger/lang/is/strings.php
@@ -1,16 +1,18 @@
strings["Post to blogger"] = "Senda færslu á bloggara";
-$a->strings["Blogger Export"] = "Flytja út blogg";
-$a->strings["Enable Blogger Post Plugin"] = "Virkja sendiviðbót fyrir blogg";
-$a->strings["Blogger username"] = "Notandanafn bloggara";
-$a->strings["Blogger password"] = "Aðgangsorð bloggara";
-$a->strings["Blogger API URL"] = "API slóð bloggs";
-$a->strings["Post to Blogger by default"] = "Sjálfgefið láta færslur flæða inn á blogg";
-$a->strings["Save Settings"] = "Vista stillingar";
-$a->strings["Post from Friendica"] = "Færslur frá Friendica";
+if (!function_exists('string_plural_select_is')) {
+ function string_plural_select_is($n)
+ {
+ return $n % 10 != 1 || $n % 100 == 11;
+ }
+}
+
+$a->strings['Post to blogger'] = 'Senda færslu á bloggara';
+$a->strings['Blogger Export'] = 'Flytja út blogg';
+$a->strings['Enable Blogger Post Plugin'] = 'Virkja sendiviðbót fyrir blogg';
+$a->strings['Blogger username'] = 'Notandanafn bloggara';
+$a->strings['Blogger password'] = 'Aðgangsorð bloggara';
+$a->strings['Blogger API URL'] = 'API slóð bloggs';
+$a->strings['Post to Blogger by default'] = 'Sjálfgefið láta færslur flæða inn á blogg';
+$a->strings['Save Settings'] = 'Vista stillingar';
+$a->strings['Post from Friendica'] = 'Færslur frá Friendica';
diff --git a/blogger/lang/it/strings.php b/blogger/lang/it/strings.php
index deea28a5..41b5b7d7 100644
--- a/blogger/lang/it/strings.php
+++ b/blogger/lang/it/strings.php
@@ -1,16 +1,18 @@
strings["Post to blogger"] = "Invia a Blogger";
-$a->strings["Blogger Export"] = "Esporta Blogger";
-$a->strings["Enable Blogger Post Plugin"] = "Abilita il plugin di invio a Blogger";
-$a->strings["Blogger username"] = "Nome utente Blogger";
-$a->strings["Blogger password"] = "Password Blogger";
-$a->strings["Blogger API URL"] = "Indirizzo API Blogger";
-$a->strings["Post to Blogger by default"] = "Invia sempre a Blogger";
-$a->strings["Save Settings"] = "Salva Impostazioni";
-$a->strings["Post from Friendica"] = "Messaggio da Friendica";
+if (!function_exists('string_plural_select_it')) {
+ function string_plural_select_it($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Post to blogger'] = 'Invia a Blogger';
+$a->strings['Blogger Export'] = 'Esporta Blogger';
+$a->strings['Enable Blogger Post Plugin'] = 'Abilita il plugin di invio a Blogger';
+$a->strings['Blogger username'] = 'Nome utente Blogger';
+$a->strings['Blogger password'] = 'Password Blogger';
+$a->strings['Blogger API URL'] = 'Indirizzo API Blogger';
+$a->strings['Post to Blogger by default'] = 'Invia sempre a Blogger';
+$a->strings['Save Settings'] = 'Salva Impostazioni';
+$a->strings['Post from Friendica'] = 'Messaggio da Friendica';
diff --git a/blogger/lang/nb-no/strings.php b/blogger/lang/nb-no/strings.php
index de7246bc..c38826e5 100644
--- a/blogger/lang/nb-no/strings.php
+++ b/blogger/lang/nb-no/strings.php
@@ -1,11 +1,11 @@
-strings["Post to blogger"] = "";
-$a->strings["Blogger Post Settings"] = "";
-$a->strings["Enable Blogger Post Plugin"] = "";
-$a->strings["Blogger username"] = "";
-$a->strings["Blogger password"] = "";
-$a->strings["Blogger API URL"] = "";
-$a->strings["Post to Blogger by default"] = "";
-$a->strings["Submit"] = "Lagre";
-$a->strings["Post from Friendica"] = "";
+strings['Post to blogger'] = '';
+$a->strings['Blogger Post Settings'] = '';
+$a->strings['Enable Blogger Post Plugin'] = '';
+$a->strings['Blogger username'] = '';
+$a->strings['Blogger password'] = '';
+$a->strings['Blogger API URL'] = '';
+$a->strings['Post to Blogger by default'] = '';
+$a->strings['Submit'] = 'Lagre';
+$a->strings['Post from Friendica'] = '';
diff --git a/blogger/lang/pl/strings.php b/blogger/lang/pl/strings.php
index a08b447b..de60bdb8 100644
--- a/blogger/lang/pl/strings.php
+++ b/blogger/lang/pl/strings.php
@@ -1,11 +1,11 @@
-strings["Post to blogger"] = "Post na blogger";
-$a->strings["Blogger Post Settings"] = "Ustawienia postów na Blogger";
-$a->strings["Enable Blogger Post Plugin"] = "";
-$a->strings["Blogger username"] = "Nazwa użytkownika na Blogger";
-$a->strings["Blogger password"] = "Hasło do Blogger";
-$a->strings["Blogger API URL"] = "";
-$a->strings["Post to Blogger by default"] = "";
-$a->strings["Submit"] = "Potwierdź";
-$a->strings["Post from Friendica"] = "Post z Friendica";
+strings['Post to blogger'] = 'Post na blogger';
+$a->strings['Blogger Post Settings'] = 'Ustawienia postów na Blogger';
+$a->strings['Enable Blogger Post Plugin'] = '';
+$a->strings['Blogger username'] = 'Nazwa użytkownika na Blogger';
+$a->strings['Blogger password'] = 'Hasło do Blogger';
+$a->strings['Blogger API URL'] = '';
+$a->strings['Post to Blogger by default'] = '';
+$a->strings['Submit'] = 'Potwierdź';
+$a->strings['Post from Friendica'] = 'Post z Friendica';
diff --git a/blogger/lang/pt-br/strings.php b/blogger/lang/pt-br/strings.php
index dcd10fab..4a408619 100644
--- a/blogger/lang/pt-br/strings.php
+++ b/blogger/lang/pt-br/strings.php
@@ -1,16 +1,18 @@
1);;
-}}
-;
-$a->strings["Post to blogger"] = "Publicar no Blogger";
-$a->strings["Blogger Export"] = "Exportador Blogger";
-$a->strings["Enable Blogger Post Plugin"] = "Habilitar plug-in para publicar no Blogger";
-$a->strings["Blogger username"] = "Nome de usuário no Blogger";
-$a->strings["Blogger password"] = "Senha do Blogger";
-$a->strings["Blogger API URL"] = "URL da API do Blogger";
-$a->strings["Post to Blogger by default"] = "Publicar no Blogger por padrão";
-$a->strings["Save Settings"] = "Salvar Configurações";
-$a->strings["Post from Friendica"] = "Postar a partir de Friendica";
+if (!function_exists('string_plural_select_pt_br')) {
+ function string_plural_select_pt_br($n)
+ {
+ return $n > 1;
+ }
+}
+
+$a->strings['Post to blogger'] = 'Publicar no Blogger';
+$a->strings['Blogger Export'] = 'Exportador Blogger';
+$a->strings['Enable Blogger Post Plugin'] = 'Habilitar plug-in para publicar no Blogger';
+$a->strings['Blogger username'] = 'Nome de usuário no Blogger';
+$a->strings['Blogger password'] = 'Senha do Blogger';
+$a->strings['Blogger API URL'] = 'URL da API do Blogger';
+$a->strings['Post to Blogger by default'] = 'Publicar no Blogger por padrão';
+$a->strings['Save Settings'] = 'Salvar Configurações';
+$a->strings['Post from Friendica'] = 'Postar a partir de Friendica';
diff --git a/blogger/lang/ro/strings.php b/blogger/lang/ro/strings.php
index f89fd4b9..0a382b8c 100644
--- a/blogger/lang/ro/strings.php
+++ b/blogger/lang/ro/strings.php
@@ -1,16 +1,18 @@
19)||(($n%100==0)&&($n!=0)))?2:1));;
-}}
-;
-$a->strings["Post to blogger"] = "Postați pe Blogger";
-$a->strings["Blogger Export"] = "Export pe Blogger ";
-$a->strings["Enable Blogger Post Plugin"] = "Activare Modul Postare pe Blogger ";
-$a->strings["Blogger username"] = "Utilizator Blogger";
-$a->strings["Blogger password"] = "Parolă Blogger ";
-$a->strings["Blogger API URL"] = "URL Cheie API Blogger ";
-$a->strings["Post to Blogger by default"] = "Postați implicit pe Blogger";
-$a->strings["Save Settings"] = "Salvare Configurări";
-$a->strings["Post from Friendica"] = "Postați din Friendica";
+if (!function_exists('string_plural_select_ro')) {
+ function string_plural_select_ro($n)
+ {
+ return $n == 1 ? 0 : ((($n % 100 > 19) || (($n % 100 == 0) && ($n != 0))) ? 2 : 1);
+ }
+}
+
+$a->strings['Post to blogger'] = 'Postați pe Blogger';
+$a->strings['Blogger Export'] = 'Export pe Blogger ';
+$a->strings['Enable Blogger Post Plugin'] = 'Activare Modul Postare pe Blogger ';
+$a->strings['Blogger username'] = 'Utilizator Blogger';
+$a->strings['Blogger password'] = 'Parolă Blogger ';
+$a->strings['Blogger API URL'] = 'URL Cheie API Blogger ';
+$a->strings['Post to Blogger by default'] = 'Postați implicit pe Blogger';
+$a->strings['Save Settings'] = 'Salvare Configurări';
+$a->strings['Post from Friendica'] = 'Postați din Friendica';
diff --git a/blogger/lang/ru/strings.php b/blogger/lang/ru/strings.php
index 086d83b4..da72b261 100644
--- a/blogger/lang/ru/strings.php
+++ b/blogger/lang/ru/strings.php
@@ -1,11 +1,11 @@
-strings["Post to blogger"] = "";
-$a->strings["Blogger Post Settings"] = "";
-$a->strings["Enable Blogger Post Plugin"] = "";
-$a->strings["Blogger username"] = "";
-$a->strings["Blogger password"] = "";
-$a->strings["Blogger API URL"] = "";
-$a->strings["Post to Blogger by default"] = "";
-$a->strings["Submit"] = "Подтвердить";
-$a->strings["Post from Friendica"] = "Сообщение от Friendica";
+strings['Post to blogger'] = '';
+$a->strings['Blogger Post Settings'] = '';
+$a->strings['Enable Blogger Post Plugin'] = '';
+$a->strings['Blogger username'] = '';
+$a->strings['Blogger password'] = '';
+$a->strings['Blogger API URL'] = '';
+$a->strings['Post to Blogger by default'] = '';
+$a->strings['Submit'] = 'Подтвердить';
+$a->strings['Post from Friendica'] = 'Сообщение от Friendica';
diff --git a/blogger/lang/sv/strings.php b/blogger/lang/sv/strings.php
index 3ec569a7..4575a404 100644
--- a/blogger/lang/sv/strings.php
+++ b/blogger/lang/sv/strings.php
@@ -1,3 +1,3 @@
-strings["Submit"] = "Spara";
+strings['Submit'] = 'Spara';
diff --git a/blogger/lang/zh-cn/strings.php b/blogger/lang/zh-cn/strings.php
index 6134a7d1..d6ad6bd0 100644
--- a/blogger/lang/zh-cn/strings.php
+++ b/blogger/lang/zh-cn/strings.php
@@ -1,11 +1,11 @@
-strings["Post to blogger"] = "转播到blogger";
-$a->strings["Blogger Post Settings"] = "Blogger转播设置";
-$a->strings["Enable Blogger Post Plugin"] = "使Blogger转播插件可用";
-$a->strings["Blogger username"] = "Blogger用户名";
-$a->strings["Blogger password"] = "Blogger密码";
-$a->strings["Blogger API URL"] = "Blogger API URL";
-$a->strings["Post to Blogger by default"] = "默认地转播到Blogger";
-$a->strings["Submit"] = "提交";
-$a->strings["Post from Friendica"] = "文章从Friendica";
+strings['Post to blogger'] = '转播到blogger';
+$a->strings['Blogger Post Settings'] = 'Blogger转播设置';
+$a->strings['Enable Blogger Post Plugin'] = '使Blogger转播插件可用';
+$a->strings['Blogger username'] = 'Blogger用户名';
+$a->strings['Blogger password'] = 'Blogger密码';
+$a->strings['Blogger API URL'] = 'Blogger API URL';
+$a->strings['Post to Blogger by default'] = '默认地转播到Blogger';
+$a->strings['Submit'] = '提交';
+$a->strings['Post from Friendica'] = '文章从Friendica';
diff --git a/buffer/buffer.php b/buffer/buffer.php
index 162600d6..be96e9a5 100644
--- a/buffer/buffer.php
+++ b/buffer/buffer.php
@@ -3,384 +3,415 @@
* Name: Buffer Post Connector
* Description: Post to Buffer (Linkedin, App.net, Google+, Facebook, Twitter)
* Version: 0.2
- * Author: Michael Vogel
+ * Author: Michael Vogel .
*/
-require('addon/buffer/bufferapp.php');
+require 'addon/buffer/bufferapp.php';
-function buffer_install() {
- register_hook('post_local', 'addon/buffer/buffer.php', 'buffer_post_local');
- register_hook('notifier_normal', 'addon/buffer/buffer.php', 'buffer_send');
- register_hook('jot_networks', 'addon/buffer/buffer.php', 'buffer_jot_nets');
- register_hook('connector_settings', 'addon/buffer/buffer.php', 'buffer_settings');
- register_hook('connector_settings_post', 'addon/buffer/buffer.php', 'buffer_settings_post');
+function buffer_install()
+{
+ register_hook('post_local', 'addon/buffer/buffer.php', 'buffer_post_local');
+ register_hook('notifier_normal', 'addon/buffer/buffer.php', 'buffer_send');
+ register_hook('jot_networks', 'addon/buffer/buffer.php', 'buffer_jot_nets');
+ register_hook('connector_settings', 'addon/buffer/buffer.php', 'buffer_settings');
+ register_hook('connector_settings_post', 'addon/buffer/buffer.php', 'buffer_settings_post');
}
-function buffer_uninstall() {
- unregister_hook('post_local', 'addon/buffer/buffer.php', 'buffer_post_local');
- unregister_hook('notifier_normal', 'addon/buffer/buffer.php', 'buffer_send');
- unregister_hook('jot_networks', 'addon/buffer/buffer.php', 'buffer_jot_nets');
- unregister_hook('connector_settings', 'addon/buffer/buffer.php', 'buffer_settings');
- unregister_hook('connector_settings_post', 'addon/buffer/buffer.php', 'buffer_settings_post');
+function buffer_uninstall()
+{
+ unregister_hook('post_local', 'addon/buffer/buffer.php', 'buffer_post_local');
+ unregister_hook('notifier_normal', 'addon/buffer/buffer.php', 'buffer_send');
+ unregister_hook('jot_networks', 'addon/buffer/buffer.php', 'buffer_jot_nets');
+ unregister_hook('connector_settings', 'addon/buffer/buffer.php', 'buffer_settings');
+ unregister_hook('connector_settings_post', 'addon/buffer/buffer.php', 'buffer_settings_post');
}
-function buffer_module() {}
-
-function buffer_content(&$a) {
-
- if(! local_user()) {
- notice( t('Permission denied.') . EOL);
- return '';
- }
-
- require_once("mod/settings.php");
- settings_init($a);
-
- if (isset($a->argv[1]))
- switch ($a->argv[1]) {
- case "connect":
- $o = buffer_connect($a);
- break;
- default:
- $o = print_r($a->argv, true);
- break;
- }
- else
- $o = buffer_connect($a);
-
- return $o;
+function buffer_module()
+{
}
-function buffer_plugin_admin(&$a, &$o){
- $t = get_markup_template( "admin.tpl", "addon/buffer/" );
+function buffer_content(&$a)
+{
+ if (!local_user()) {
+ notice(t('Permission denied.').EOL);
- $o = replace_macros($t, array(
- '$submit' => t('Save Settings'),
- // name, label, value, help, [extra values]
- '$client_id' => array('client_id', t('Client ID'), get_config('buffer', 'client_id' ), ''),
- '$client_secret' => array('client_secret', t('Client Secret'), get_config('buffer', 'client_secret' ), ''),
- ));
-}
-function buffer_plugin_admin_post(&$a){
- $client_id = ((x($_POST,'client_id')) ? notags(trim($_POST['client_id'])) : '');
- $client_secret = ((x($_POST,'client_secret')) ? notags(trim($_POST['client_secret'])): '');
- set_config('buffer','client_id',$client_id);
- set_config('buffer','client_secret',$client_secret);
- info( t('Settings updated.'). EOL );
+ return '';
+ }
+
+ require_once 'mod/settings.php';
+ settings_init($a);
+
+ if (isset($a->argv[1])) {
+ switch ($a->argv[1]) {
+ case 'connect':
+ $o = buffer_connect($a);
+ break;
+ default:
+ $o = print_r($a->argv, true);
+ break;
+ }
+ } else {
+ $o = buffer_connect($a);
+ }
+
+ return $o;
}
-function buffer_connect(&$a) {
+function buffer_plugin_admin(&$a, &$o)
+{
+ $t = get_markup_template('admin.tpl', 'addon/buffer/');
- if (isset($_REQUEST["error"])) {
- $o = t('Error when registering buffer connection:')." ".$_REQUEST["error"];
- return $o;
- }
- // Start a session. This is necessary to hold on to a few keys the callback script will also need
- session_start();
-
- // Define the needed keys
- $client_id = get_config('buffer','client_id');
- $client_secret = get_config('buffer','client_secret');
-
- // The callback URL is the script that gets called after the user authenticates with buffer
- $callback_url = $a->get_baseurl()."/buffer/connect";
-
- $buffer = new BufferApp($client_id, $client_secret, $callback_url);
-
- if (!$buffer->ok) {
- $o .= 'Connect to Buffer!';
- } else {
- logger("buffer_connect: authenticated");
- $o .= t("You are now authenticated to buffer. ");
- $o .= ' '.t("return to the connector page").'';
- set_pconfig(local_user(), 'buffer','access_token', $buffer->access_token);
- }
-
- return($o);
+ $o = replace_macros($t, array(
+ '$submit' => t('Save Settings'),
+ // name, label, value, help, [extra values]
+ '$client_id' => array('client_id', t('Client ID'), get_config('buffer', 'client_id'), ''),
+ '$client_secret' => array('client_secret', t('Client Secret'), get_config('buffer', 'client_secret'), ''),
+ ));
+}
+function buffer_plugin_admin_post(&$a)
+{
+ $client_id = ((x($_POST, 'client_id')) ? notags(trim($_POST['client_id'])) : '');
+ $client_secret = ((x($_POST, 'client_secret')) ? notags(trim($_POST['client_secret'])) : '');
+ set_config('buffer', 'client_id', $client_id);
+ set_config('buffer', 'client_secret', $client_secret);
+ info(t('Settings updated.').EOL);
}
-function buffer_jot_nets(&$a,&$b) {
- if(! local_user())
- return;
+function buffer_connect(&$a)
+{
+ if (isset($_REQUEST['error'])) {
+ $o = t('Error when registering buffer connection:').' '.$_REQUEST['error'];
- $buffer_post = get_pconfig(local_user(),'buffer','post');
- if(intval($buffer_post) == 1) {
- $buffer_defpost = get_pconfig(local_user(),'buffer','post_by_default');
- $selected = ((intval($buffer_defpost) == 1) ? ' checked="checked" ' : '');
- $b .= '
'
- . t('Post to Buffer') . '
';
- }
+ return $o;
+ }
+ // Start a session. This is necessary to hold on to a few keys the callback script will also need
+ session_start();
+
+ // Define the needed keys
+ $client_id = get_config('buffer', 'client_id');
+ $client_secret = get_config('buffer', 'client_secret');
+
+ // The callback URL is the script that gets called after the user authenticates with buffer
+ $callback_url = $a->get_baseurl().'/buffer/connect';
+
+ $buffer = new BufferApp($client_id, $client_secret, $callback_url);
+
+ if (!$buffer->ok) {
+ $o .= 'Connect to Buffer!';
+ } else {
+ logger('buffer_connect: authenticated');
+ $o .= t('You are now authenticated to buffer. ');
+ $o .= ' '.t('return to the connector page').'';
+ set_pconfig(local_user(), 'buffer', 'access_token', $buffer->access_token);
+ }
+
+ return $o;
}
-function buffer_settings(&$a,&$s) {
-
- if(! local_user())
- return;
-
- /* Add our stylesheet to the page so we can make our settings look nice */
-
- $a->page['htmlhead'] .= '' . "\r\n";
-
- /* Get the current state of our config variables */
-
- $enabled = get_pconfig(local_user(),'buffer','post');
- $checked = (($enabled) ? ' checked="checked" ' : '');
- $css = (($enabled) ? '' : '-disabled');
-
- $def_enabled = get_pconfig(local_user(),'buffer','post_by_default');
- $def_checked = (($def_enabled) ? ' checked="checked" ' : '');
-
- /* Add some HTML to the existing form */
-
- $s .= '';
- $s .= '
".t('You can download public events from: ').$a->get_baseurl()."/cal/username/export/ical
";
- } elseif ($a->argc==4) {
- // get the parameters from the request we just received
- $username = $a->argv[1];
- $do = $a->argv[2];
- $format = $a->argv[3];
- // check that there is a user matching the requested profile
- $r = q("SELECT uid FROM user WHERE nickname='".$username."' LIMIT 1;");
- if (count($r))
- {
- $uid = $r[0]['uid'];
- } else {
- killme();
- }
- // if we shall do anything other then export, end here
- if (! $do == 'export' )
- killme();
- // check if the user allows us to share the profile
- $enable = get_pconfig( $uid, 'cal', 'enable');
- if (! $enable == 1) {
- info(t('The user does not export the calendar.'));
- return;
- }
- // we are allowed to show events
- // get the timezone the user is in
- $r = q("SELECT timezone FROM user WHERE uid=".$uid." LIMIT 1;");
- if (count($r))
- $timezone = $r[0]['timezone'];
- // does the user who requests happen to be the owner of the events
- // requested? then show all of your events, otherwise only those that
- // don't have limitations set in allow_cid and allow_gid
- if (local_user() == $uid) {
- $r = q("SELECT `start`, `finish`, `adjust`, `summary`, `desc`, `location` FROM `event` WHERE `uid`=".$uid." and `cid`=0;");
- } else {
- $r = q("SELECT `start`, `finish`, `adjust`, `summary`, `desc`, `location` FROM `event` WHERE `allow_cid`='' and `allow_gid`='' and `uid`='".$uid."' and `cid`='0';");
- }
- // we have the events that are available for the requestor
- // now format the output according to the requested format
- $res = cal_format_output($r, $format, $timezone);
- if (! $res=='')
- info($res);
- } else {
- // wrong number of parameters
- killme();
+ $o .= '
'.t('Event Export').'
'.t('You can download public events from: ').$a->get_baseurl().'/cal/username/export/ical
';
+ } elseif ($a->argc == 4) {
+ // get the parameters from the request we just received
+ $username = $a->argv[1];
+ $do = $a->argv[2];
+ $format = $a->argv[3];
+ // check that there is a user matching the requested profile
+ $r = q("SELECT uid FROM user WHERE nickname='".$username."' LIMIT 1;");
+ if (count($r)) {
+ $uid = $r[0]['uid'];
+ } else {
+ killme();
+ }
+ // if we shall do anything other then export, end here
+ if (!$do == 'export') {
+ killme();
}
+ // check if the user allows us to share the profile
+ $enable = get_pconfig($uid, 'cal', 'enable');
+ if (!$enable == 1) {
+ info(t('The user does not export the calendar.'));
+
+ return;
+ }
+ // we are allowed to show events
+ // get the timezone the user is in
+ $r = q('SELECT timezone FROM user WHERE uid='.$uid.' LIMIT 1;');
+ if (count($r)) {
+ $timezone = $r[0]['timezone'];
+ }
+ // does the user who requests happen to be the owner of the events
+ // requested? then show all of your events, otherwise only those that
+ // don't have limitations set in allow_cid and allow_gid
+ if (local_user() == $uid) {
+ $r = q('SELECT `start`, `finish`, `adjust`, `summary`, `desc`, `location` FROM `event` WHERE `uid`='.$uid.' and `cid`=0;');
+ } else {
+ $r = q("SELECT `start`, `finish`, `adjust`, `summary`, `desc`, `location` FROM `event` WHERE `allow_cid`='' and `allow_gid`='' and `uid`='".$uid."' and `cid`='0';");
+ }
+ // we have the events that are available for the requestor
+ // now format the output according to the requested format
+ $res = cal_format_output($r, $format, $timezone);
+ if (!$res == '') {
+ info($res);
+ }
+ } else {
+ // wrong number of parameters
+ killme();
+ }
+
return $o;
}
-function cal_format_output ($r, $f, $tz)
+function cal_format_output($r, $f, $tz)
{
$res = t('This calendar format is not supported');
- switch ($f)
- {
- // format the exported data as a CSV file
- case "csv":
- header("Content-type: text/csv");
- $o = '"Subject", "Start Date", "Start Time", "Description", "End Date", "End Time", "Location"' . PHP_EOL;
- foreach ($r as $rr) {
-// TODO the time / date entries don't include any information about the
+ switch ($f) {
+ // format the exported data as a CSV file
+ case 'csv':
+ header('Content-type: text/csv');
+ $o = '"Subject", "Start Date", "Start Time", "Description", "End Date", "End Time", "Location"'.PHP_EOL;
+ foreach ($r as $rr) {
+ // TODO the time / date entries don't include any information about the
// timezone the event is scheduled in :-/
- $tmp1 = strtotime($rr['start']);
- $tmp2 = strtotime($rr['finish']);
- $time_format = "%H:%M:%S";
- $date_format = "%Y-%m-%d";
- $o .= '"'.$rr['summary'].'", "'.strftime($date_format, $tmp1) .
- '", "'.strftime($time_format, $tmp1).'", "'.$rr['desc'] .
- '", "'.strftime($date_format, $tmp2) .
- '", "'.strftime($time_format, $tmp2) .
- '", "'.$rr['location'].'"' . PHP_EOL;
- }
- echo $o;
- killme();
+ $tmp1 = strtotime($rr['start']);
+ $tmp2 = strtotime($rr['finish']);
+ $time_format = '%H:%M:%S';
+ $date_format = '%Y-%m-%d';
+ $o .= '"'.$rr['summary'].'", "'.strftime($date_format, $tmp1).
+ '", "'.strftime($time_format, $tmp1).'", "'.$rr['desc'].
+ '", "'.strftime($date_format, $tmp2).
+ '", "'.strftime($time_format, $tmp2).
+ '", "'.$rr['location'].'"'.PHP_EOL;
+ }
+ echo $o;
+ killme();
- case "ical":
- header("Content-type: text/ics");
- $o = 'BEGIN:VCALENDAR'. PHP_EOL
- . 'VERSION:2.0' . PHP_EOL
- . 'PRODID:-//friendica calendar export//0.1//EN' . PHP_EOL;
+ case 'ical':
+ header('Content-type: text/ics');
+ $o = 'BEGIN:VCALENDAR'.PHP_EOL
+ .'VERSION:2.0'.PHP_EOL
+ .'PRODID:-//friendica calendar export//0.1//EN'.PHP_EOL;
// TODO include timezone informations in cases were the time is not in UTC
// see http://tools.ietf.org/html/rfc2445#section-4.8.3
// . 'BEGIN:VTIMEZONE' . PHP_EOL
@@ -117,62 +119,68 @@ function cal_format_output ($r, $f, $tz)
// TODO instead of PHP_EOL CRLF should be used for long entries
// but test your solution against http://icalvalid.cloudapp.net/
// also long lines SHOULD be split at 75 characters length
- foreach ($r as $rr) {
- if ($rr['adjust'] == 1) {
- $UTC = 'Z';
- } else {
- $UTC = '';
- }
- $o .= 'BEGIN:VEVENT' . PHP_EOL;
- if ($rr[start]) {
- $tmp = strtotime($rr['start']);
- $dtformat = "%Y%m%dT%H%M%S".$UTC;
- $o .= 'DTSTART:'.strftime($dtformat, $tmp).PHP_EOL;
- }
- if ($rr['finish']) {
- $tmp = strtotime($rr['finish']);
- $dtformat = "%Y%m%dT%H%M%S".$UTC;
- $o .= 'DTEND:'.strftime($dtformat, $tmp).PHP_EOL;
- }
- if ($rr['summary'])
- $tmp = $rr['summary'];
- $tmp = str_replace(PHP_EOL, PHP_EOL.' ',$tmp);
- $tmp = addcslashes($tmp, ',;');
- $o .= 'SUMMARY:' . $tmp . PHP_EOL;
- if ($rr['desc'])
- $tmp = $rr['desc'];
- $tmp = str_replace(PHP_EOL, PHP_EOL.' ',$tmp);
- $tmp = addcslashes($tmp, ',;');
- $o .= 'DESCRIPTION:' . $tmp . PHP_EOL;
- if ($rr['location']) {
- $tmp = $rr['location'];
- $tmp = str_replace(PHP_EOL, PHP_EOL.' ',$tmp);
- $tmp = addcslashes($tmp, ',;');
- $o .= 'LOCATION:' . $tmp . PHP_EOL;
- }
- $o .= 'END:VEVENT' . PHP_EOL;
- }
- $o .= 'END:VCALENDAR' . PHP_EOL;
- echo $o;
- killme();
+ foreach ($r as $rr) {
+ if ($rr['adjust'] == 1) {
+ $UTC = 'Z';
+ } else {
+ $UTC = '';
+ }
+ $o .= 'BEGIN:VEVENT'.PHP_EOL;
+ if ($rr[start]) {
+ $tmp = strtotime($rr['start']);
+ $dtformat = '%Y%m%dT%H%M%S'.$UTC;
+ $o .= 'DTSTART:'.strftime($dtformat, $tmp).PHP_EOL;
+ }
+ if ($rr['finish']) {
+ $tmp = strtotime($rr['finish']);
+ $dtformat = '%Y%m%dT%H%M%S'.$UTC;
+ $o .= 'DTEND:'.strftime($dtformat, $tmp).PHP_EOL;
+ }
+ if ($rr['summary']) {
+ $tmp = $rr['summary'];
+ }
+ $tmp = str_replace(PHP_EOL, PHP_EOL.' ', $tmp);
+ $tmp = addcslashes($tmp, ',;');
+ $o .= 'SUMMARY:'.$tmp.PHP_EOL;
+ if ($rr['desc']) {
+ $tmp = $rr['desc'];
+ }
+ $tmp = str_replace(PHP_EOL, PHP_EOL.' ', $tmp);
+ $tmp = addcslashes($tmp, ',;');
+ $o .= 'DESCRIPTION:'.$tmp.PHP_EOL;
+ if ($rr['location']) {
+ $tmp = $rr['location'];
+ $tmp = str_replace(PHP_EOL, PHP_EOL.' ', $tmp);
+ $tmp = addcslashes($tmp, ',;');
+ $o .= 'LOCATION:'.$tmp.PHP_EOL;
+ }
+ $o .= 'END:VEVENT'.PHP_EOL;
+ }
+ $o .= 'END:VCALENDAR'.PHP_EOL;
+ echo $o;
+ killme();
}
+
return $res;
}
-function cal_addon_settings_post ( &$a, &$b )
+function cal_addon_settings_post(&$a, &$b)
{
- if (! local_user())
- return;
+ if (!local_user()) {
+ return;
+ }
- if (!x($_POST,'cal-submit'))
- return;
+ if (!x($_POST, 'cal-submit')) {
+ return;
+ }
- set_pconfig(local_user(),'cal','enable',intval($_POST['cal-enable']));
+ set_pconfig(local_user(), 'cal', 'enable', intval($_POST['cal-enable']));
}
-function cal_addon_settings ( &$a, &$s )
+function cal_addon_settings(&$a, &$s)
{
- if (! local_user())
- return;
+ if (!local_user()) {
+ return;
+ }
$enabled = get_pconfig(local_user(), 'cal', 'enable');
$checked = (($enabled) ? ' checked="checked" ' : '');
@@ -189,12 +197,10 @@ function cal_addon_settings ( &$a, &$s )
$s .= '
';
$s .= '
'.t('If this is enabled, your public events will be available at').' '.$url.'
';
$s .= '
'.t('Currently supported formats are ical and csv.').'
';
$s .= '';
}
-
-?>
diff --git a/cal/lang/C/strings.php b/cal/lang/C/strings.php
index a72dc119..d4535ccc 100644
--- a/cal/lang/C/strings.php
+++ b/cal/lang/C/strings.php
@@ -1,12 +1,12 @@
strings["Event Export"] = "";
-$a->strings["You can download public events from: "] = "";
-$a->strings["The user does not export the calendar."] = "";
-$a->strings["This calendar format is not supported"] = "";
-$a->strings["Export Events"] = "";
-$a->strings["If this is enabled, your public events will be available at"] = "";
-$a->strings["Currently supported formats are ical and csv."] = "";
-$a->strings["Enable calendar export"] = "";
-$a->strings["Submit"] = "";
+
+$a->strings['Event Export'] = '';
+$a->strings['You can download public events from: '] = '';
+$a->strings['The user does not export the calendar.'] = '';
+$a->strings['This calendar format is not supported'] = '';
+$a->strings['Export Events'] = '';
+$a->strings['If this is enabled, your public events will be available at'] = '';
+$a->strings['Currently supported formats are ical and csv.'] = '';
+$a->strings['Enable calendar export'] = '';
+$a->strings['Submit'] = '';
diff --git a/cal/lang/cs/strings.php b/cal/lang/cs/strings.php
index 9a99079d..177a02ab 100644
--- a/cal/lang/cs/strings.php
+++ b/cal/lang/cs/strings.php
@@ -1,16 +1,18 @@
=2 && $n<=4) ? 1 : 2;;
-}}
-;
-$a->strings["Event Export"] = "Export událostí";
-$a->strings["You can download public events from: "] = "Veřejné události si můžete stánout z:";
-$a->strings["The user does not export the calendar."] = "Uživatel kalenář neexportuje.";
-$a->strings["This calendar format is not supported"] = "Tento kalendářový formát není podporován.";
-$a->strings["Export Events"] = "Export událostí";
-$a->strings["If this is enabled, your public events will be available at"] = "Pokud je toto povoleno, vaše veřejné události budou viditelné na";
-$a->strings["Currently supported formats are ical and csv."] = "Aktuálně podporované formáty jsou ical a csv.";
-$a->strings["Enable calendar export"] = "Povolit export kalendáře";
-$a->strings["Save Settings"] = "Uložit Nastavení";
+if (!function_exists('string_plural_select_cs')) {
+ function string_plural_select_cs($n)
+ {
+ return ($n == 1) ? 0 : ($n >= 2 && $n <= 4) ? 1 : 2;
+ }
+}
+
+$a->strings['Event Export'] = 'Export událostí';
+$a->strings['You can download public events from: '] = 'Veřejné události si můžete stánout z:';
+$a->strings['The user does not export the calendar.'] = 'Uživatel kalenář neexportuje.';
+$a->strings['This calendar format is not supported'] = 'Tento kalendářový formát není podporován.';
+$a->strings['Export Events'] = 'Export událostí';
+$a->strings['If this is enabled, your public events will be available at'] = 'Pokud je toto povoleno, vaše veřejné události budou viditelné na';
+$a->strings['Currently supported formats are ical and csv.'] = 'Aktuálně podporované formáty jsou ical a csv.';
+$a->strings['Enable calendar export'] = 'Povolit export kalendáře';
+$a->strings['Save Settings'] = 'Uložit Nastavení';
diff --git a/cal/lang/de/strings.php b/cal/lang/de/strings.php
index 39359271..75a6e6ef 100644
--- a/cal/lang/de/strings.php
+++ b/cal/lang/de/strings.php
@@ -1,16 +1,18 @@
strings["Event Export"] = "Ereignis Export";
-$a->strings["You can download public events from: "] = "Du kannst öffentliche Ereignisse hier herunterladen;";
-$a->strings["The user does not export the calendar."] = "Diese_r Nutzer_in exportiert den Kalender nicht.";
-$a->strings["This calendar format is not supported"] = "Dieses Kalenderformat wird nicht unterstützt.";
-$a->strings["Export Events"] = "Exportiere Ereignisse";
-$a->strings["If this is enabled, your public events will be available at"] = "Wenn dies aktiviert ist, werden alle öffentliche Ereignisse unter folgender URL verfügbar sein";
-$a->strings["Currently supported formats are ical and csv."] = "Derzeit werden die Formate ical und csv unterstützt.";
-$a->strings["Enable calendar export"] = "Kalenderexport aktivieren";
-$a->strings["Save Settings"] = "Einstellungen speichern";
+if (!function_exists('string_plural_select_de')) {
+ function string_plural_select_de($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Event Export'] = 'Ereignis Export';
+$a->strings['You can download public events from: '] = 'Du kannst öffentliche Ereignisse hier herunterladen;';
+$a->strings['The user does not export the calendar.'] = 'Diese_r Nutzer_in exportiert den Kalender nicht.';
+$a->strings['This calendar format is not supported'] = 'Dieses Kalenderformat wird nicht unterstützt.';
+$a->strings['Export Events'] = 'Exportiere Ereignisse';
+$a->strings['If this is enabled, your public events will be available at'] = 'Wenn dies aktiviert ist, werden alle öffentliche Ereignisse unter folgender URL verfügbar sein';
+$a->strings['Currently supported formats are ical and csv.'] = 'Derzeit werden die Formate ical und csv unterstützt.';
+$a->strings['Enable calendar export'] = 'Kalenderexport aktivieren';
+$a->strings['Save Settings'] = 'Einstellungen speichern';
diff --git a/cal/lang/fr/strings.php b/cal/lang/fr/strings.php
index b3517062..6e8a179d 100644
--- a/cal/lang/fr/strings.php
+++ b/cal/lang/fr/strings.php
@@ -1,16 +1,18 @@
1);;
-}}
-;
-$a->strings["Event Export"] = "Exportation d'événement";
-$a->strings["You can download public events from: "] = "Vous pouvez télécharger les événements publiques de :";
-$a->strings["The user does not export the calendar."] = "L'utilisateur n'exporte pas le calendrier.";
-$a->strings["This calendar format is not supported"] = "Ce format de calendrier n'est pas pris en charge";
-$a->strings["Export Events"] = "Exporter les événements";
-$a->strings["If this is enabled, your public events will be available at"] = "Si activé, vos événements publiques seront disponible à";
-$a->strings["Currently supported formats are ical and csv."] = "Les formats actuellement pris en charge sont ical et csv.";
-$a->strings["Enable calendar export"] = "Activer l'export de calendrier";
-$a->strings["Save Settings"] = "Sauvegarder les paramètres";
+if (!function_exists('string_plural_select_fr')) {
+ function string_plural_select_fr($n)
+ {
+ return $n > 1;
+ }
+}
+
+$a->strings['Event Export'] = "Exportation d'événement";
+$a->strings['You can download public events from: '] = 'Vous pouvez télécharger les événements publiques de :';
+$a->strings['The user does not export the calendar.'] = "L'utilisateur n'exporte pas le calendrier.";
+$a->strings['This calendar format is not supported'] = "Ce format de calendrier n'est pas pris en charge";
+$a->strings['Export Events'] = 'Exporter les événements';
+$a->strings['If this is enabled, your public events will be available at'] = 'Si activé, vos événements publiques seront disponible à';
+$a->strings['Currently supported formats are ical and csv.'] = 'Les formats actuellement pris en charge sont ical et csv.';
+$a->strings['Enable calendar export'] = "Activer l'export de calendrier";
+$a->strings['Save Settings'] = 'Sauvegarder les paramètres';
diff --git a/cal/lang/it/strings.php b/cal/lang/it/strings.php
index c7f228bb..dd48f339 100644
--- a/cal/lang/it/strings.php
+++ b/cal/lang/it/strings.php
@@ -1,16 +1,18 @@
strings["Event Export"] = "Esporta Evento";
-$a->strings["You can download public events from: "] = "Puoi scaricare gli eventi publici da:";
-$a->strings["The user does not export the calendar."] = "L'utente non esporta il calendario.";
-$a->strings["This calendar format is not supported"] = "Il formato del calendario non è supportato";
-$a->strings["Export Events"] = "Esporta Eventi";
-$a->strings["If this is enabled, your public events will be available at"] = "Se abilitato, i tuoi eventi pubblici saranno disponibili a";
-$a->strings["Currently supported formats are ical and csv."] = "I formati supportati sono ical e csv.";
-$a->strings["Enable calendar export"] = "Abilita esporazione calendario";
-$a->strings["Save Settings"] = "Salva Impostazioni";
+if (!function_exists('string_plural_select_it')) {
+ function string_plural_select_it($n)
+ {
+ return $n != 1;
+ }
+}
+
+$a->strings['Event Export'] = 'Esporta Evento';
+$a->strings['You can download public events from: '] = 'Puoi scaricare gli eventi publici da:';
+$a->strings['The user does not export the calendar.'] = "L'utente non esporta il calendario.";
+$a->strings['This calendar format is not supported'] = 'Il formato del calendario non è supportato';
+$a->strings['Export Events'] = 'Esporta Eventi';
+$a->strings['If this is enabled, your public events will be available at'] = 'Se abilitato, i tuoi eventi pubblici saranno disponibili a';
+$a->strings['Currently supported formats are ical and csv.'] = 'I formati supportati sono ical e csv.';
+$a->strings['Enable calendar export'] = 'Abilita esporazione calendario';
+$a->strings['Save Settings'] = 'Salva Impostazioni';
diff --git a/cal/lang/pt-br/strings.php b/cal/lang/pt-br/strings.php
index 69e35ea5..1c9b8501 100644
--- a/cal/lang/pt-br/strings.php
+++ b/cal/lang/pt-br/strings.php
@@ -1,16 +1,18 @@
1);;
-}}
-;
-$a->strings["Event Export"] = "Exportar Evento";
-$a->strings["You can download public events from: "] = "Você pode baixar eventos públicos de:";
-$a->strings["The user does not export the calendar."] = "O usuário não exportou o calendário.";
-$a->strings["This calendar format is not supported"] = "Esse formato de calendário não é suportado.";
-$a->strings["Export Events"] = "Exporta Eventos";
-$a->strings["If this is enabled, your public events will be available at"] = "Se isso estiver habiltiado, seus eventos públicos estarão disponíveis";
-$a->strings["Currently supported formats are ical and csv."] = "Os formatos disponíveis atualmente são ical e csv.";
-$a->strings["Enable calendar export"] = "Habilite exportar calendário";
-$a->strings["Save Settings"] = "Salvar as Configurações";
+if (!function_exists('string_plural_select_pt_br')) {
+ function string_plural_select_pt_br($n)
+ {
+ return $n > 1;
+ }
+}
+
+$a->strings['Event Export'] = 'Exportar Evento';
+$a->strings['You can download public events from: '] = 'Você pode baixar eventos públicos de:';
+$a->strings['The user does not export the calendar.'] = 'O usuário não exportou o calendário.';
+$a->strings['This calendar format is not supported'] = 'Esse formato de calendário não é suportado.';
+$a->strings['Export Events'] = 'Exporta Eventos';
+$a->strings['If this is enabled, your public events will be available at'] = 'Se isso estiver habiltiado, seus eventos públicos estarão disponíveis';
+$a->strings['Currently supported formats are ical and csv.'] = 'Os formatos disponíveis atualmente são ical e csv.';
+$a->strings['Enable calendar export'] = 'Habilite exportar calendário';
+$a->strings['Save Settings'] = 'Salvar as Configurações';
diff --git a/cal/lang/ro/strings.php b/cal/lang/ro/strings.php
index 8e328e98..e643ccd4 100644
--- a/cal/lang/ro/strings.php
+++ b/cal/lang/ro/strings.php
@@ -1,16 +1,18 @@
19)||(($n%100==0)&&($n!=0)))?2:1));;
-}}
-;
-$a->strings["Event Export"] = "Exportare Eveniment";
-$a->strings["You can download public events from: "] = "Puteți descărca evenimente publice de la:";
-$a->strings["The user does not export the calendar."] = "Utilizatorul nu își exportă calendarul.";
-$a->strings["This calendar format is not supported"] = "Acest format de calendar nu este acceptat";
-$a->strings["Export Events"] = "Exportați Evenimente";
-$a->strings["If this is enabled, your public events will be available at"] = "Dacă este activat, evenimente dvs publice vor fi disponibile pe";
-$a->strings["Currently supported formats are ical and csv."] = "Formate acceptate în prezent sunt ical şi csv.";
-$a->strings["Enable calendar export"] = "Activați exportarea calendarului";
-$a->strings["Save Settings"] = "Salvare Configurări";
+if (!function_exists('string_plural_select_ro')) {
+ function string_plural_select_ro($n)
+ {
+ return $n == 1 ? 0 : ((($n % 100 > 19) || (($n % 100 == 0) && ($n != 0))) ? 2 : 1);
+ }
+}
+
+$a->strings['Event Export'] = 'Exportare Eveniment';
+$a->strings['You can download public events from: '] = 'Puteți descărca evenimente publice de la:';
+$a->strings['The user does not export the calendar.'] = 'Utilizatorul nu își exportă calendarul.';
+$a->strings['This calendar format is not supported'] = 'Acest format de calendar nu este acceptat';
+$a->strings['Export Events'] = 'Exportați Evenimente';
+$a->strings['If this is enabled, your public events will be available at'] = 'Dacă este activat, evenimente dvs publice vor fi disponibile pe';
+$a->strings['Currently supported formats are ical and csv.'] = 'Formate acceptate în prezent sunt ical şi csv.';
+$a->strings['Enable calendar export'] = 'Activați exportarea calendarului';
+$a->strings['Save Settings'] = 'Salvare Configurări';
diff --git a/calc/calc.php b/calc/calc.php
index a299d45e..db7a6bec 100755
--- a/calc/calc.php
+++ b/calc/calc.php
@@ -1,363 +1,361 @@
-
- */
-
-
-function calc_install() {
- register_hook('app_menu', 'addon/calc/calc.php', 'calc_app_menu');
-}
-
-function calc_uninstall() {
- unregister_hook('app_menu', 'addon/calc/calc.php', 'calc_app_menu');
-
-}
-
-function calc_app_menu($a,&$b) {
- $b['app_menu'][] = '