Commit inicial - WordPress Análisis de Precios Unitarios

- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,338 @@
<?php
namespace bizpanda\includes\gates\twitter;
use bizpanda\includes\gates\exceptions\GateBridgeException;
use bizpanda\includes\gates\OAuthGateBridge;
/**
* The class to proxy the request to the Twitter API.
*/
class TwitterBridge extends OAuthGateBridge {
const API_ENDPOINT = 'https://api.twitter.com/';
const API_VERSION = '1.1';
const API_OAUTH_VERSION = '1.0';
/**
* Get a request_token from Twitter
* @param array $stateParams
* @return mixed[]
* @throws GateBridgeException
*/
function getRequestToken( $stateParams = [] ) {
$callbackUrl = $this->callbackUrl;
if ( !empty( $stateParams ) ) {
if ( strpos( $callbackUrl, '?' ) === false ) {
$callbackUrl .= '?' . http_build_query( $stateParams );
} else {
$callbackUrl .= '&' . http_build_query( $stateParams );
}
}
$response = $this->requestQuery('oauth/request_token', 'POST', [
'oauthParams' => [
'oauth_callback' => $callbackUrl
],
// the parameter 'x_auth_access_type' doesn't work with include_email option
// 'data' => [
// 'x_auth_access_type' => $this->permissions
// ],
'expectQuery' => true
]);
if ( !isset( $response['oauth_token'] ) ) {
throw $this->createException( GateBridgeException::UNEXPECTED_RESPONSE, 'The parameter [oauth_token] is not set.' );
}
return $response;
}
/**
* Gets a redirect URL to authorize a user.
* @param array $stateParams Extra data for the state param if applied.
* @return string
* @throws GateBridgeException
*/
function getAuthorizeURL( $stateParams = [] ) {
$token = $this->getRequestToken( $stateParams );
$token = $token['oauth_token'];
return self::API_ENDPOINT . 'oauth/authorize' . "?oauth_token={$token}";
}
/**
* Exchange request token and secret for an access token and
* secret, to sign API calls.
*
* @returns array("oauth_token" => "the-access-token",
* "oauth_token_secret" => "the-access-secret",
* "user_id" => "9436992",
* "screen_name" => "abraham")
*/
function getAccessTokenByVerifier( $token, $verifier ) {
$host = 'oauth/access_token?oauth_token=' . $token . '&oauth_verifier=' . $verifier;
return $this->requestQuery( $host, 'POST');
}
/**
* @inheritDoc
*/
function getAccessToken($code) {
throw GateBridgeException::create( GateBridgeException::NOT_SUPPORTED );
}
/**
* @inheritDoc
*/
function getUserInfo(){
return $this->get('account/verify_credentials', [
'skip_status' => 1,
'include_email' => 'true'
]);
return $result;
}
// -----------------------------------------------------------------------------
// Helper Methods
// -----------------------------------------------------------------------------
/**
* Makes GET request to the API.
* @param $host
* @param $data
* @return string
* @throws GateBridgeException
*/
public function get($host, $data) {
return $this->requestJson( $host, 'GET', [
'data' => $data
]);
}
/**
* Makes POST request to the API.
* @param $host
* @param $data
* @return string
* @throws GateBridgeException
*/
public function post($host, $data) {
return $this->requestJson( $host, 'POST', [
'data' => $data
]);
}
/**
* Makes a request to API and expects the query string as a response.
* @param $host
* @param $method
* @param array $options
* @return mixed[]
* @throws GateBridgeException
*/
function requestQuery($host, $method, $options = [] ) {
$options['expectQuery'] = true;
$data = $this->request( $host, $method, $options );
return $this->throwExceptionOnErrors( $data );
}
/**
* Makes a request to API and expects the json as a response.
* @param $host
* @param $method
* @param array $options
* @return string
* @throws GateBridgeException
*/
function requestJson( $host, $method, $options = [] ) {
$options['expectJson'] = true;
$json = $this->request( $host, $method, $options );
return $this->throwExceptionOnErrors( $json );
}
/**
* A common point for any request to Twitter API.
* @param $host
* @param $method
* @param array $options
* @return mixed[]
* @throws GateBridgeException
*/
function request($host, $method, $options = [] ) {
$isOAuthRequest = ( strpos( $host, 'oauth' ) === 0 );
if ( $isOAuthRequest ) {
$url = self::API_ENDPOINT . $host;
} else {
$url = self::API_ENDPOINT . self::API_VERSION . '/' . $host . '.json';
}
$signUrl = $url;
$authorizationParams = [
'oauth_consumer_key' => $this->clientId,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_timestamp' => $this->generateTimestamp(),
'oauth_nonce' => $this->generateNonce(),
'oauth_version' => self::API_OAUTH_VERSION
];
// if this request is authorized, add the access token
if ( $this->accessToken ) {
$authorizationParams['oauth_token'] = $this->accessToken;
}
// if the options extra parameters to pass, add it too
if ( isset( $options['oauthParams'] )) {
$authorizationParams = array_merge($authorizationParams, $options['oauthParams'] );
}
// adds all GET/POST params to the signature
$urlParams = [];
$query = parse_url($url, PHP_URL_QUERY );
parse_str( $query, $urlParams );
// filters empty params, otherwise we will get an incorrect signature
$postParams = !empty( $options['data'] ) ? $options['data'] : [];
$postParamsFiltered = [];
foreach( $postParams as $postParamName => $postParam ) {
if ( $postParam === null || $postParam === false ) continue;
$postParamsFiltered[$postParamName] = $postParam;
}
$options['data'] = $postParamsFiltered;
$signatureParams = array_merge($authorizationParams, $urlParams, $postParamsFiltered);
$authorizationParams['oauth_signature'] = $this->signRequest($method, $url, $signatureParams);
$headers =[
'Authorization' => $this->generateAuthorizationHeader( $authorizationParams )
];
if ( !isset( $options['headers'] ) ) $options['headers'] = [];
$options['headers'] = array_merge( $options['headers'], $headers);
$json = $this->http( $url, $method, $options );
/*
if ( $host == 'account/verify_credentials' ) {
return [
'url' => $url,
'signatureParams' => $signatureParams,
'authorizationParams' => $authorizationParams,
'urlParams' => $urlParams,
'postParams' => $postParams,
'options' => $options,
'content' => $json,
'request' => $this->getLastRequestInfo(),
'response' => $this->getLastResponseInfo(),
'sign-key' => $this->generateSigningKey(),
'access-token' => $this->accessToken,
'access-token-secret' => $this->accessTokenSecret,
];
}
*/
return $json;
}
/**
* Throws an exception if the response contains errors.
* @param $data
* @return mixed[] Returns response data back.
* @throws GateBridgeException
*/
function throwExceptionOnErrors( $data ) {
if ( isset( $data['errors'] ) && isset( $data['errors'][0]['message'] ) ) {
// [CODE: 32] Could not authenticate you.
if ( 32 === $data['errors'][0]['code'] ) {
throw $this->createException( GateBridgeException::NOT_AUTHENTICATED, 'Please make sure that Twitter API Key and Secret Key are set correctly.' );
}
$clarification = sprintf( '[CODE: %d] %s.' , $data['errors'][0]['code'], $data['errors'][0]['message'] );
throw $this->createException( GateBridgeException::ERROR_RESPONSE, $clarification );
}
return $data;
}
/**
* Signs the request.
* @param $method
* @param $url
* @param $params
* @return string
*/
function signRequest( $method, $url, $params ) {
ksort( $params );
$strParams = [];
foreach( $params as $key => $value ) {
$strParams[] = rawurlencode( $key ) . '=' . rawurlencode( $value );
}
$strParams = implode('&', $strParams);
$message = $method . '&'. rawurlencode($url) . '&' . rawurlencode($strParams);
$key = $this->generateSigningKey();
$encrypted = hash_hmac('sha1', $message, $key, true);
return base64_encode($encrypted);
}
/**
* Generates the signing key.
* @return string
*/
function generateSigningKey() {
$key = rawurlencode( $this->clientSecret ) . '&';
if ( $this->accessTokenSecret ) $key = $key . rawurlencode( $this->accessTokenSecret );
return $key;
}
/**
* Generates the authorization header.
* @param array $params
* @return string
*/
function generateAuthorizationHeader( $params = [] ) {
$header = 'OAuth ';
ksort( $params );
$strParams = [];
foreach( $params as $key => $value ) {
$strParams[] = rawurlencode( $key ) . '="' . rawurlencode( $value ) . '"';
}
$strParams = implode(', ', $strParams);
return $header . $strParams;
}
}

View File

@@ -0,0 +1,251 @@
<?php
namespace bizpanda\includes\gates\twitter;
use bizpanda\includes\gates\exceptions\GateBridgeException;
use bizpanda\includes\gates\Gate;
use bizpanda\includes\gates\exceptions\GateException;
use bizpanda\includes\gates\google\FacebookBridge;
use bizpanda\includes\gates\OAuthGate;
use Yii;
/**
* The class to proxy the request to the Twitter API.
*/
class TwitterGate extends OAuthGate {
public function __construct($session = null, $config = null, $request = null)
{
parent::__construct($session, $config, $request);
$this->name = 'twitter';
$this->allowedRequestTypes = array_merge(
$this->allowedRequestTypes,
['follow', 'tweet', 'get_tweets', 'get_followers']
);
$this->allowedPermissionScopes = ['read', 'write'];
}
/**
* @inheritDoc
*/
public function createBridge( $authorized = false ) {
$config = $this->getOptionsForBridge( $authorized );
return new TwitterBridge( $config );
}
/**
* @inheritDoc
*/
public function getOptionsForBridge( $authorized = false ) {
$scopes = $this->getFlowScopes();
$scope = $scopes[0]; // read or write
$twitterOptions = $this->config->get( $this->name );
$options = $twitterOptions[$scope];
$options['callbackUrl'] = $twitterOptions['callbackUrl'];
if ( !isset( $options['clientId'] ) || !isset( $options['clientSecret'] ) ) {
throw GateException::create(GateException::APP_NOT_CONFIGURED, 'API Key or API Secret are not set.' );
}
$options['permissions'] = $scope;
if ( $authorized ) {
$options['accessToken'] = $this->getVisitorValue($this->name . '_oauth_token', null );
$options['accessTokenSecret'] = $this->getVisitorValue($this->name . '_oauth_secret', null );
if ( empty( $options['accessToken'] ) ) {
throw GateException::create(GateException::AUTH_FLOW_BROKEN, 'The access token is not set.' );
}
if ( empty( $options['accessTokenSecret'] ) ) {
throw GateException::create(GateException::AUTH_FLOW_BROKEN, 'The access token secret is not set.' );
}
}
return $options;
}
/**
* @inheritDoc
*/
public function doCallback() {
$token = $this->getRequestParam('oauthToken');
$verifier = $this->getRequestParam('oauthVerifier');
if ( empty( $token ) || empty( $verifier ) ) {
throw GateException::create(GateException::INVALID_INBOUND_REQUEST, 'Parameters [oauthToken] or [oauthVerifier] are not passed.' );
}
$bridge = $this->createBridge( false );
$accessToken = $bridge->getAccessTokenByVerifier( $token, $verifier );
$this->setVisitorValue($this->name . '_oauth_token', $accessToken['oauth_token'] );
$this->setVisitorValue($this->name . '_oauth_secret', $accessToken['oauth_token_secret'] );
return $this->prepareResult([
'userId' => $accessToken['user_id'],
'oauthToken' => $accessToken['oauth_token'],
'oauthTokenSecret' => $accessToken['oauth_token_secret']
]);
}
/**
* @inheritDoc
*/
public function doGetUserInfo() {
$bridge = $this->createBridge(true);
$response = $bridge->getUserInfo();
$identity = [
'source' => 'twitter',
'email' => isset( $response['email'] ) ? $response['email'] : false,
'name' => isset( $response['name'] ) ? $response['name'] : false,
'displayName' => isset( $response['screen_name'] ) ? $response['screen_name'] : false,
'twitterId' => isset( $response['screen_name'] ) ? $response['screen_name'] : false,
'twitterUrl' => isset( $response['screen_name'] ) ? ( 'https://twitter.com/' . $response['screen_name'] ) : ''
];
if ( $identity['name'] ) {
$nameParts = explode(' ', $identity['name']);
if ( count( $nameParts ) == 2 ) {
$identity['name'] = $nameParts[0];
$identity['family'] = $nameParts[1];
}
}
if ( isset( $response['profile_image_url'] ) ) {
$identity['image'] = str_replace('_normal', '', $response['profile_image_url']);
} else {
$identity['image'] = false;
}
return $this->prepareResult([
'identity' => $identity
]);
}
/**
* Gets the 3 last tweets.
* @return array
* @throws GateBridgeException
*/
public function doGetTweets() {
$bridge = $this->createBridge(true);
$response = $bridge->get('statuses/user_timeline', [
'count' => 3
]);
return $this->prepareResult([
'response' => $response
]);
}
/**
* Finds a followers with the specified screen name.
* @return array
* @throws GateException
*/
public function doGetFollowers() {
$bridge = $this->createBridge(true);
$screenName = $this->getRequestParam('screenName');
if ( empty( $screenName) ) throw new GateException( "The screen name is not set." );
$response = $bridge->get('friendships/lookup', [
'screen_name' => $screenName
]);
return $this->prepareResult([
'response' => $response
]);
}
/**
* Tweets the specified message.
* @return array
* @throws GateException
*/
protected function doTweet() {
$bridge = $this->createBridge(true);
$message = $this->getRequestParam('tweetMessage');
if ( empty( $message) ) throw new GateException( "The tweet text is not specified." );
$response = null;
try {
$response = $bridge->post('statuses/update', [
'status' => $message
]);
return $this->prepareResult([
'response' => $response
]);
} catch ( GateBridgeException $exception ) {
$details = $exception->getExceptionDetails();
if ( strpos( $details['clarification'], '187' ) > 0 ) {
// error 187: status is a duplicate.
// already tweeted
return $this->prepareResult([
'success' => true
]);
} else {
throw $exception;
}
}
}
/**
* Follows the specified profile.
* @return array
* @throws GateException
*/
protected function doFollow() {
$bridge = $this->createBridge(true);
$followTo = $this->getRequestParam('followTo');
if ( empty( $followTo) ) throw new GateException( "The user name to follow is not specified" );
$notifications = $this->getRequestParam('notifications', true);
$notifications = $this->normalizeValue( $notifications );
$response = $bridge->get('friendships/lookup', [
'screen_name' => $followTo
]);
if ( isset( $response[0]->connections ) && in_array( 'following', $response[0]->connections ) ) {
return $this->prepareResult([
'success' => true
]);
}
$requestData = ['screen_name' => $followTo];
if ( !empty( $notifications ) ) $requestData['follow'] = $notifications;
$response = $bridge->post('friendships/create', $requestData);
return $this->prepareResult([
'response' => $response
]);
}
}