I have 3 questions (need help):
I do not know, how to run this plugin (gives me fatal error) please check my script (I am beginner)
Need help with admin page to set up APIkey and choose language for call url http://xxx.CZ or http://xxx.SK (This page is not scripted yet)
How to add my plugin admin page to woocommerce admin page?
This plugin is for Woocommerce. It is supposed to call specific URL (http://heureka.cz/or .sk/dotaznik/"Clients API set up in admin page in woocommerce"/"Customers email"/"Order ID"/"bought Products ID"/) when customers order si complete.
I am beginner in PHP and Wordpress. Thank you all for helping me.
CODE:
<?php
/*
Plugin Name: Overené zákazníkmi Heureka
Plugin URI: http://www.podujatie.eu
Version: 0.1
Description:
Author: Podujatie.eu, Ing. Igor Kóňa
Tested up to: 3.6
Author URI: http://www.podujatie.eu
Text Domain: woocommerce-new-badge
License: GNU General Public License v3.0
License URI: http://www.gnu.org/licenses/gpl-3.0.html
*/
/**
* Check if WooCommerce is active
**/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
if ( ! class_exists( 'WC_HO' ) ) {
class WC_HO {
function heurekaovereno( $order_id ) {
error_log( "Order complete for order $order_id", 0 ); }
add_action( 'woocommerce_order_status_completed', 'heurekaovereno' );
// order object (optional but handy)
$order = new WC_Order( $order_id );
// do some stuff here
private function sendRequest($url)
{
$parsed = parse_url($url);
$fp = fsockopen($parsed['host'], 80, $errno, $errstr, 5);
if (!$fp) {
throw new HeurekaOverenoException($errstr . ' (' . $errno . ')');
} else {
$return = '';
$out = "GET " . $parsed['path'] . "?" . $parsed['query'] . " HTTP/1.1\r\n" .
"Host: " . $parsed['host'] . "\r\n" .
"Connection: Close\r\n\r\n";
fputs($fp, $out);
while (!feof($fp)) {
$return .= fgets($fp, 128);
}
fclose($fp);
$returnParsed = explode("\r\n\r\n", $return);
return empty($returnParsed[1]) ? '' : trim($returnParsed[1]);
}
}
/**
* Sends request to Heureka Overeno service and checks for valid response
*
* #return boolean true
*/
public function send()
{
if (empty($this->email)) {
throw new HeurekaOverenoException('Customer email address not set');
}
// create URL
$url = $this->getUrl() . '?id=' . $this->apiKey . '&email=' . urlencode($this->email);
foreach ($this->products as $product) {
$url .= '&produkt[]=' . urlencode($product);
}
foreach ($this->productsItemId as $itemId) {
$url .= '&itemId[]=' . urlencode($itemId);
}
// add order ID
if (isset($this->orderId)) {
$url .= '&orderid=' . urlencode($this->orderId);
}
// send request and check for valid response
$contents = $this->sendRequest($url);
if ($contents == FALSE) {
throw new HeurekaOverenoException('Unable to create HTTP request to Heureka Overeno service');
} elseif ($contents == self::RESPONSE_OK) {
return TRUE;
} else {
throw new HeurekaOverenoException($contents);
}
}
/**
* Adds ordered products using item ID
*
* #param string $itemId Ordered product item ID
*/
public function addProductItemId($itemId)
{
$this->productsItemId[] = $itemId;
}
/**
* Adds ordered products using name
*
* Products names should be provided in UTF-8 encoding. The service can handle
* WINDOWS-1250 and ISO-8859-2 if necessary
*
* #param string $productName Ordered product name
*/
public function addProduct($productName)
{
$this->products[] = $productName;
}
/**
* Heureka endpoint URL
*
* #var string
*/
const BASE_URL = 'http://www.heureka.cz/direct/dotaznik/objednavka.php';
const BASE_URL_SK = 'http://www.heureka.sk/direct/dotaznik/objednavka.php';
/**
* Language IDs
*
* #var int
*/
const LANGUAGE_CZ = 1;
const LANGUAGE_SK = 2;
/**
* Valid response value
*
* #var string
*/
const RESPONSE_OK = 'ok';
/**
* Shop API key
*
* #var string
*/
private $apiKey;
/**
* Customer email
*
* #var string
*/
private $email;
/**
* Ordered products
*
* #var array
*/
private $products = array();
/**
* Order ID
*
* #var int
*/
private $orderId;
/**
* Current language identifier
*
* #var int
*/
private $languageId = 1;
/**
* Ordered products provided using item ID
*
* #var array
*/
private $productsItemId = array();
/**
* Initialize Heureka Overeno service
*
* #param string $apiKey Shop API key
* #param int $languageId Language version settings
*/
public function __construct($apiKey, $languageId = self::LANGUAGE_CZ)
{
$this->setApiKey($apiKey);
$this->languageId = $languageId;
}
/**
* Sets API key and check well-formedness
*
* #param string $apiKey Shop api key
*/
public function setApiKey($apiKey)
{
if (preg_match('(^[0-9abcdef]{32}$)', $apiKey)) {
$this->apiKey = $apiKey;
} else {
throw new OverflowException('Api key ' . $apiKey . ' is invalid.');
}
}
/**
* Sets customer email
*
* #param string $email Customer email address
*/
public function setEmail($email)
{
$this->email = $email;
}
// Default options
add_option( 'wc_nb_newness', '30' );
// Admin
add_action( 'woocommerce_settings_image_options_after', array( $this, 'admin_settings' ), 20);
add_action( 'woocommerce_update_options_catalog', array( $this, 'save_admin_settings' ) );
/*-----------------------------------------------------------------------------------*/
/* Class Functions */
/*-----------------------------------------------------------------------------------*/
// Load the settings
function admin_settings() {
woocommerce_admin_fields( $this->settings );
}
// Save the settings
function save_admin_settings() {
woocommerce_update_options( $this->settings );
}
if (!isset($wpdb)) $wpdb = $GLOBALS['wpdb'];
$heurekaovereno_ver = '1.00';
$WC_HO = new WC_HO();
}
}
}
?>
This script works (it has few bugs, but it works) only when you put it in functions.php
Here is where I am asking, why is it.
Related
I am creating a woocommerce custom shipping method. Its working fine, but when I use the shipping calculator it doesn't refresh.
<?php
/**
* Plugin Name: Expresso Jundiaí for WooCommerce
* Plugin URI: https://valoremarketing.com.br
* Description: Adds Expresso Jundiaí shipping methods to your WooCommerce store.
* Author: Valore + NSC
* Author URI: https://valoremarketing.com.br
* Version: 1.0.0
* License: GPLv2 or later
*
*/
if (!defined('ABSPATH')) {
exit;
}
/*
* Check if WooCommerce is active
*/
if (in_array('woocommerce/woocommerce.php', apply_filters('active_plugins', get_option('active_plugins')))) {
function expresso_jundiai_shipping_method()
{
if (!class_exists('Expresso_Jundiai_Shipping_Method')) {
class Expresso_Jundiai_Shipping_Method extends WC_Shipping_Method
{
private $args = '';
/**
* Constructor
*
* #access public
* #return void
*/
public function __construct($instance_id = 0)
{
$this->id = 'expresso-jundiai';
$this->title = 'Expresso Jundiaí';
$this->instance_id = absint($instance_id);
$this->method_title = __('Expresso Jundiaí Entregas', 'expresso-jundiai');
$this->method_description = __('Entregas feitas por Expresso Jundiaí', 'expresso-jundiai');
/**
* Utilized to woocommerce to verify the supported features by the shipping method
*/
$this->supports = array(
'shipping-zones',
'instance-settings',
'instance-settings-modal',
'settings'
);
$this->init();
}
/**
* Init your settings
*
* #access public
* #return void
*/
public function init()
{
$this->init_form_fields();
$this->init_settings();
/// Actions.
add_action('woocommerce_update_options_shipping_' . $this->id, array($this, 'process_admin_options'));
}
/**
* Define settings field for this shipping
*
* To access the fields:
* $shipping_methods = WC()->shipping->get_shipping_methods();
* foreach ( $shipping_methods as $key => $shipping_method ) {
* $code = $shipping_method->settings->code;
* }
*
* #return void
*/
public function init_form_fields()
{...}
/**
* Get the args needed to make a post request to API target
*
* #param $package
* #return mixed
*/
private function get_request_args( $package )
{...}
/**
* This function is used to calculate the shipping cost.
* Within this function we can check for weights, dimensions and other parameters in package.
*
* #access public
* #param mixed $package
* #return void
*/
public function calculate_shipping( $package = array() )
{
$args = $this->get_request_args( $package );
$uri = $this->get_option( 'apiUri' );
$response = $this->request_to_api( $uri, $args );
if ($response !== NULL) {
$this->add_rate( array(
'id' => $this->id,
'label' => $this->title,
'package' => $package,
'cost' => $response->vlrFrete,
) );
}
}
/**
* Calculates the cubage of all products.
*
* #param $package
* #return float|int
*/
private function get_total_cubage( $package ) {
$total = 0;
foreach ( $package['contents'] as $item_id => $values )
{
$_product = $values['data'];
$height = (float) $_product->get_height();
$width = (float) $_product->get_width();
$length = (float) $_product->get_length();
$total += $height * $width * $length;
}
return ( ($total > 0) ? ( $total/1000000 ) : 0 );
}
/**
* #param $package
* #return int
*/
private function get_total_volumes( $package ) {
$total = 0;
foreach ( $package['contents'] as $item_id => $values ) {
$total += (int) $values['quantity'];
}
return $total;
}
/**
* Calculate the total wheight of all products of the order
* #param $package
* #return float|int
*/
private function get_order_total_weight( $package ) {
$total = 0;
foreach ( $package['contents'] as $item_id => $values )
{
$_product = $values['data'];
$_product_weight = (float) $_product->get_weight();
$total += $_product_weight * $values['quantity'];
}
$total = wc_get_weight( $total, 'kg' );
return $total;
}
/**
* #param $uri
* #param $args
* #return mixed|void
*/
private function request_to_api( $uri, $args )
{
$response = wp_remote_post( $uri, $args );
var_dump($args, $response);
if ( is_wp_error( $response ) || '200' != wp_remote_retrieve_response_code( $response )) {
return;
}
$body = json_decode( wp_remote_retrieve_body( $response ) );
if ( empty( $body ) )
return;
return $body;
}
}
}
}
add_action('woocommerce_shipping_init', 'expresso_jundiai_shipping_method');
/**
* Adds the name of class into shipping methods
*
* #param $methods
* #return array
*/
function add_expresso_jundiai_shipping_method($methods)
{
/**
* The key of the array $method must match the shipping method id
*/
$methods['expresso-jundiai'] = 'Expresso_Jundiai_Shipping_Method';
return $methods;
}
add_filter('woocommerce_shipping_methods', 'add_expresso_jundiai_shipping_method');
}
I need it to recalculate with the same rules when i use the shipping calculator in cart... when wordpress calls /?wc-ajax=update_shipping_method
I' trying two days... Please... help
It just my thought i just want to do like the same, I haven't try this because of i haven't any idea about this means how it will be done.
For Example:
I have - mysite.com/view?user_id=12 , I don't want to show url's parameters (?user_id=12) on url, On the place of this, I want to show like
mysite.com/view?_signature=encryptedparameter
(like : mysite.com/view?_signature=853ef7a0ff5aea6f24152b1d1ed4d771)
853ef7a0ff5aea6f24152b1d1ed4d771 will denotes user_id=12.
If i have multiple parameters it would be like the same and i will have a single encrypted string and i will get all parameters with that string.
Yes but i am using in Laravel 5.1
assume if i have "mysite.com/view?user_id=12"
And i want "mysite.com/view?_signature=encryptedparameter"
Please fallow some steps
laravel>packages>myfolder>core
+=>folder
-=>file
+packages
+Folder
+core
+src
+Faundation
-Application.php
+Routing
-RoutingServiceProvider.php
-UriGenerator.php
+Support
+Middleware
-UrlParamRevealerMiddleware.php
+ServiceProvider
-CoreServiceProvider.php
-UriParamProtector.php
<<IN APPLICATION.PHP>>
<?php
namespace Folder\Core\Foundation;
use Illuminate\Events\EventServiceProvider;
use Folder\Core\Routing\RoutingServiceProvider;
use Illuminate\Foundation\Application as BaseApplication;
use Folder\Core\Support\ServiceProvider\CoreServiceProvider;
class Application extends BaseApplication
{
/**
* Register all of the base service providers.
*
* #return void
*/
protected function registerBaseServiceProviders()
{
$this->register(new EventServiceProvider($this));
$this->register(new CoreServiceProvider($this));
$this->register(new RoutingServiceProvider($this));
}
}
<<//IN APPLICATION.PHP>>
<<-RoutingServiceProvider>>
<?php
namespace Folder\Core\Routing;
use Folder\Core\Routing\UrlGenerator;
use Illuminate\Routing\RoutingServiceProvider as BaseServiceProvider;
class RoutingServiceProvider extends BaseServiceProvider
{
/**
* Register the URL generator service.
*
* #return void
*/
protected function registerUrlGenerator()
{
$this->app['url'] = $this->app->share(function ($app) {
$routes = $app['router']->getRoutes();
// The URL generator needs the route collection that exists on the router.
// Keep in mind this is an object, so we're passing by references here
// and all the registered routes will be available to the generator.
$app->instance('routes', $routes);
$url = $this->getUrlGenerator($routes);
$url->setSessionResolver(function () {
return $this->app['session'];
});
// If the route collection is "rebound", for example, when the routes stay
// cached for the application, we will need to rebind the routes on the
// URL generator instance so it has the latest version of the routes.
$app->rebinding('routes', function ($app, $routes) {
$app['url']->setRoutes($routes);
});
return $url;
});
}
/**
* Get the url generator instance.
*
* #param \Illuminate\Routing\RouteCollection $routes
* #return \Folder\Core\Routing\UrlGenerator
*/
protected function getUrlGenerator($routes)
{
$url = new UrlGenerator(
$routes,
$this->app->rebinding(
'request',
$this->requestRebinder()
)
);
return $url;
}
}
<</-RoutingServiceProvider>>
<<UriGenerator.php>>
<?php
namespace Folder\Core\Routing;
use ErrorException;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Routing\UrlGenerator as BaseUrlGenerator;
class UrlGenerator extends BaseUrlGenerator
{
/**
* Get the URL to a named route.
*
* #param string $name
* #param mixed $parameters
* #param bool $absolute
* #return string
*
* #throws \InvalidArgumentException
*/
public function route($name, $parameters = [], $absolute = true)
{
$encryptedParameters = $parameters;
if (Auth::guest() === false) {
$encryptedParameters = $this->encrypt($name, $parameters);
}
return parent::route($name, $encryptedParameters, $absolute);
}
/**
* Get the cryptic engine.
*
* #return \Folder\Core\Support\UrlParamEncrypter
*
* #throws \ErrorException
*/
protected function getCrypt()
{
$app = App::getInstance();
if (isset($app['urlencryptor'])) {
return $app['urlencryptor'];
}
throw new ErrorException('URL Encryptor was not found.');
}
/**
* Get the protector engine.
*
* #return #return \Folder\Core\Support\UrlParamProtector
*
* #throws \ErrorException
*/
protected function getProtector()
{
$app = App::getInstance();
if (isset($app['urlprotector'])) {
return $app['urlprotector'];
}
throw new ErrorException('URL Protector was not found.');
}
/**
* Encrypts the parameter passed as querystring in URL.
*
* #param array $parameters
* #return array
*/
protected function encrypt($routeName, $parameters = [])
{
if (! is_array($parameters)) {
return $parameters;
}
if (count($parameters) === 0) {
return [];
}
if (Auth::guest() === true) {
return $parameters;
}
$protected = $this->getProtector()->protect($routeName, $parameters);
return ['__signature' => $protected];
}
}
<<//UriGenerator.php>>
<<UrlParamRevealerMiddleware.php>>
<?php
namespace Folder\Core\Support\Middleware;
use Closure;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Folder\Core\Support\UrlParamProtector;
class UrlParamRevealerMiddleware
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
(! Auth::guest()) && App::make(UrlParamProtector::class)->reveal($request);
return $next($request);
}
}
<<//UrlParamRevealerMiddleware.php>>
<<CoreServiceProvider.php>>
<?php
namespace Folder\Core\Support\ServiceProvider;
use Illuminate\Support\ServiceProvider;
use Folder\Core\Support\UrlParamProtector;
class CoreServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
$this->app->make('Illuminate\Contracts\Http\Kernel')
->pushMiddleware('Folder\Core\Support\Middleware\UrlParamRevealerMiddleware');
}
/**
* Register the service provider.
*
* #return void
*/
public function register()
{
$this->registerUrlProtector();
}
/**
* Register UrlProtector class.
*/
protected function registerUrlProtector()
{
$this->app->singleton('urlprotector', function () {
return new UrlParamProtector();
});
}
}
<<//CoreServiceProvider.php>>
<<-UriParamProtector.php>>
<?php
namespace Folder\Core\Support;
use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
class UrlParamProtector
{
/**
* Session key.
*
* #var string
*/
protected $sessionKey = '__url_protector__';
/**
* Request class.
*
* #var \Illuminate\Http\Request
*/
protected $request;
/**
* Values those needs to be merged in request object.
*
* #var array
*/
protected $valuesToBeMerged;
/**
* Create and returns VALID RFC 4211 COMPLIANT
* Universally Unique IDentifiers (UUID) version 4.
*
* #return string
*/
protected function getNewGuid()
{
if (function_exists('com_create_guid') === true) {
return trim(com_create_guid(), '{}');
}
return sprintf(
'%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(16384, 20479),
mt_rand(32768, 49151),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535)
);
}
/**
* Create the route key.
*
* #param string $routeName
* #param array $parameters
* #return string
*/
protected function getRouteKey($routeName, array $parameters = [])
{
if (count($parameters) <= 0) {
$paramToString = '';
} else {
$paramToString = implode('-', array_map(
function ($k, $v) {
return $k . '-' . $v;
},
array_keys($parameters),
array_values($parameters)
));
}
$routeKey = 'route__' . $routeName . (empty($paramToString) ? '' : '-' . $paramToString);
return $routeKey;
}
/**
* Returns a GUID for a URL parameter.
*
* #param string $routeName
* #param array $parameters
* #return string
*/
public function protect($routeName, array $parameters)
{
$routeKey = $this->getRouteKey($routeName, $parameters);
if (Session::has($this->sessionKey . '.' . $routeKey) === false) {
$guid = Str::lower($this->getNewGuid());
Session::set($this->sessionKey . '.' . $routeKey, [
'guid' => $guid,
'loggedin_user_id' => (Auth::guest() ? 0 : Auth::user()->id),
'params' => $parameters,
]);
} else {
$guid = Session::get($this->sessionKey . '.' . $routeKey . '.guid');
}
return $guid;
}
/**
* Check whether guid passed is a valid one or not.
*
* #param string $guid
* #return boolean
*/
protected function isValidGuid($guid)
{
foreach (Session::get($this->sessionKey) as $key => $value) {
if (!isset($value['guid'])) {
list($innerKey, $val) = each($value);
} else {
$val = $value;
}
if ($val['guid'] === $guid) {
$this->valuesToBeMerged = $val['params'];
return true;
}
}
return false;
}
/**
* Check whether guid passed is a valid one or not.
*
* #param string $guid
* #return boolean
*/
public function isValidGuidForPost($guid)
{
foreach (Session::get($this->sessionKey) as $key => $value) {
if ($value['guid'] === $guid && Auth::user()->id === $value['loggedin_user_id']) {
$this->valuesToBeMerged = $value['params'];
return true;
}
}
return false;
}
/**
* Merge the request with our revealed values.
*/
protected function mergeRequest()
{
$this->request->merge($this->valuesToBeMerged);
}
/**
* Check whether a "__signature" is correct or not.
*
* #param \Illuminate\Http\Request $request
* #return boolean
*/
public function reveal(Request &$request)
{
$this->request = $request;
$guid = ($this->request->query('__signature') ? : false);
if ($guid === false) {
return false;
}
if ($this->isValidGuid($guid) === false) {
App::abort(400);
}
$this->mergeRequest();
}
}
<<//-UriParamProtector.php>>
==============================================
after that in "bootstrap>App.php"
use this=>
$app = new Folder\Core\Foundation\Application(
realpath(__DIR__.'/../')
);
instad of =>
$app = new Illuminate\Foundation\Application(
realpath(__DIR__.'/../')
);
in any link use "data-href"
<a data-href="route('modify_lead_status',['user_id' => $users->id])" href="javascript:void(0)"><i class=\"fa fa-random\"></i></a>"
and after that any controller,Routing,middleware will be same.....
>>composer auto-dump
<<Please check spealing be sure use same>>
i hope this is help full....thanks
I am using revolution slider plugin . I am getting above error on one of my front end form. There is one file called db.class.php in that plugin where I am getting this error. Here is the code in that file..
<?php
class UniteDBRev{
private $wpdb;
private $lastRowID;
/**
*
* constructor - set database object
*/
public function __construct(){
global $wpdb;
$this->wpdb = $wpdb;
}
/**
*
* throw error
*/
private function throwError($message,$code=-1){
UniteFunctionsRev::throwError($message,$code);
}
//------------------------------------------------------------
// validate for errors
private function checkForErrors($prefix = ""){
if(mysql_error()){
$query = $this->wpdb->last_query;
$message = $this->wpdb->last_error;
if($prefix) $message = $prefix.' - <b>'.$message.'</b>';
if($query) $message .= '<br>---<br> Query: ' . $query;
$this->throwError($message);
}
}
/**
*
* insert variables to some table
*/
public function insert($table,$arrItems){
global $wpdb;
$this->wpdb->insert($table, $arrItems);
$this->checkForErrors("Insert query error");
$this->lastRowID = $wpdb->insert_id;
return($this->lastRowID);
}
/**
*
* get last insert id
*/
public function getLastInsertID(){
global $wpdb;
$this->lastRowID = $wpdb->insert_id;
return($this->lastRowID);
}
/**
*
* delete rows
*/
public function delete($table,$where){
UniteFunctionsRev::validateNotEmpty($table,"table name");
UniteFunctionsRev::validateNotEmpty($where,"where");
$query = "delete from $table where $where";
$this->wpdb->query($query);
$this->checkForErrors("Delete query error");
}
/**
*
* run some sql query
*/
public function runSql($query){
$this->wpdb->query($query);
$this->checkForErrors("Regular query error");
}
/**
*
* insert variables to some table
*/
public function update($table,$arrItems,$where){
$response = $this->wpdb->update($table, $arrItems, $where);
if($response === false)
UniteFunctionsRev::throwError("no update action taken!");
$this->checkForErrors("Update query error");
return($this->wpdb->num_rows);
}
/**
*
* get data array from the database
*
*/
public function fetch($tableName,$where="",$orderField="",$groupByField="",$sqlAddon=""){
global $wpdb;
$query = "select * from $tableName";
if($where) $query .= " where $where";
if($orderField) $query .= " order by $orderField";
if($groupByField) $query .= " group by $groupByField";
if($sqlAddon) $query .= " ".$sqlAddon;
$response = $this->wpdb->get_results($query,ARRAY_A);
$this->checkForErrors("fetch");
return($response);
}
/**
*
* fetch only one item. if not found - throw error
*/
public function
fetchSingle($tableName,$where="",$orderField="",$groupByField="",$sqlAddon=""){
$response = $this->fetch($tableName, $where, $orderField, $groupByField, $sqlAddon);
if(empty($response))
$this->throwError("Record not found");
$record = $response[0];
return($record);
}
/**
*
* escape data to avoid sql errors and injections.
*/
public function escape($string){
$string = esc_sql($string);
return($string);
}
}
?>
I am getting this error in fetch function. I have tried with global $wpdb. But no luck. I have loaded wp-load.php also but no luck.
I have this situation:
unit:
sqkm: Square Kilometers
my_translation: Size is %size% ## I want to append the value of unit.sqkm here ##
Is there a way to reference the translation of the unit.sqkm inside the my_translation key?
Edit: Please note that i do know how i can do this via twig. My question is: is there a way to do this in the translation files.
I extended Symfony Tanslator for this:
<?php
namespace Bundle\Program\Translation;
use Symfony\Bundle\FrameworkBundle\Translation\Translator as BaseTranslator;
class Translator extends BaseTranslator
{
/**
* Uses Symfony Translator to translate, but enables referencing other translations via ##code##
*/
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
{
$text = parent::trans($id, $parameters, $domain, $locale);
$translations = [];
$delimiter = "##";
$strLen = strlen($delimiter);
$pos = strpos($text, $delimiter);
while ($pos !== false) {
$startsAt = $pos + $strLen;
$endsAt = strpos($text, $delimiter, $startsAt);
$translations[] = $delimiter . substr($text, $startsAt, $endsAt - $startsAt) . $delimiter;
$pos = strpos($text, $delimiter, $endsAt + $strLen);
}
foreach ($translations as $translation) {
$translationTrim = str_replace($delimiter, '', $translation);
$text = str_replace($translation, $this->trans($translationTrim, $parameters, $domain, $locale), $text);
}
return $text;
}
}
Then replace the Symfony translator class via parameters:
parameters:
translator.class: Bundle\Program\Translation\Translator
Now you can reference other translations via ##other.translation## INSIDE your yml file.
In your Twig template, try this :
{{ 'my_translation' | trans({'%size%': size, 'unit.sqkm' : ('unit.sqkm'|trans)}) }}
You can use translated values inside other translations.
{{ 'paragraph' | trans({ '%size%': 3, '%unit%': 'unit' | trans()}) }}
Where unit itself is another key for a translation. Your translation file however could look like this:
paragraph: Size is %size% %unit%
unit: Square Kilometers
If, like me, you want to achieve this in Symfony 4.1, here's your solution
(many thanks to #Kim's answer and #Aurelijus Rozenas's answer, all credits -apart my 4 hours trying that- go to them)
First, create your new Translator class (here: src/Common/ReferenceTranslator.php)
I can't manage to find a solution where I would extend the base translator class straight in the class code, let me know if you have one
# src/Common/ReferenceTranslator.php
namespace App\Common;
use Symfony\Component\Translation\TranslatorBagInterface;
use Symfony\Component\Translation\TranslatorInterface;
class ReferenceTranslator implements TranslatorInterface, TranslatorBagInterface
{
/** #var TranslatorBagInterface|TranslatorInterface */
protected $translator;
/**
* #param TranslatorInterface|TranslatorBagInterface $translator
*/
public function __construct($translator)
{
$this->translator = $translator;
}
/**
* Uses Symfony Translator to translate, but enables referencing other translations via ##code##
* #param $id
* #param array $parameters
* #param null $domain
* #param null $locale
* #return mixed|string
*/
public function trans($id, array $parameters = array(), $domain = null, $locale = null)
{
$text = $this->translator->trans($id, $parameters, $domain, $locale);
$translations = [];
$delimiter = "##";
$strLen = strlen($delimiter);
$pos = strpos($text, $delimiter);
while ($pos !== false) {
$startsAt = $pos + $strLen;
$endsAt = strpos($text, $delimiter, $startsAt);
$translations[] = $delimiter . substr($text, $startsAt, $endsAt - $startsAt) . $delimiter;
$pos = strpos($text, $delimiter, $endsAt + $strLen);
}
foreach ($translations as $translation) {
$translationTrim = str_replace($delimiter, '', $translation);
$text = str_replace($translation, $this->trans($translationTrim, $parameters, $domain, $locale), $text);
}
return $text;
}
/**
* #param string $id
* #param int $number
* #param array $parameters
* #param null $domain
* #param null $locale
*
* #return string
*/
public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null)
{
return $this->translator->transChoice($id, $number, $parameters, $domain, $locale);
}
/**
* #param string $locale
*/
public function setLocale($locale)
{
$this->translator->setLocale($locale);
}
/**
* #return string
*/
public function getLocale()
{
return $this->translator->getLocale();
}
/**
* #param string|null $locale
*
* #return \Symfony\Component\Translation\MessageCatalogueInterface
*/
public function getCatalogue($locale = null)
{
return $this->translator->getCatalogue($locale);
}
}
And then edit your services.yaml file
# app/config/services.yml
#[...]
services:
#[...]
# Custom Translator (References)
# Overrides the Translator Service (is still available as #app.decorating_translator.inner)
app.decorating_translator:
class: App\Common\ReferenceTranslator
decorates: translator
arguments:
- '#app.decorating_translator.inner'
public: false
And voilà !
Again, don't hesitate if you know how to improve this, as I'm not a Symfony expert !
The TBG answer works,
for Symfony 4.4 here is the code in service.yaml
Services
App\Common\ReferenceTranslator:
arguments:
$translator: '#translator'
And dont forget to implement LocaleAwareInterface too !
Anyone know which option is needed to compress all css in one line. I am using a wordpress plugin called bwp-minify, however the plugin's css level of compression is low and i am trying to change it through the YUICompressor.php
I tried changing line-break to 0 and to 100000 but none have effect.
Is it the following;
--line-break
Some source control tools don't like files containing lines longer than,
say 8000 characters. The linebreak option is used in that case to split
long lines after a specific column. It can also be used to make the code
more readable, easier to debug (especially with the MS Script Debugger)
Specify 0 to get a line break after each semi-colon in JavaScript, and
after each rule in CSS.
Source Code:
<?php
/**
* Class Minify_YUICompressor
* #package Minify
*/
/**
* Compress Javascript/CSS using the YUI Compressor
*
* You must set $jarFile and $tempDir before calling the minify functions.
* Also, depending on your shell's environment, you may need to specify
* the full path to java in $javaExecutable or use putenv() to setup the
* Java environment.
*
* <code>
* Minify_YUICompressor::$jarFile = '/path/to/yuicompressor-2.3.5.jar';
* Minify_YUICompressor::$tempDir = '/tmp';
* $code = Minify_YUICompressor::minifyJs(
* $code
* ,array('nomunge' => true, 'line-break' => 1000)
* );
* </code>
*
* #todo unit tests, $options docs
*
* #package Minify
* #author Stephen Clay <steve#mrclay.org>
*/
class Minify_YUICompressor {
/**
* Filepath of the YUI Compressor jar file. This must be set before
* calling minifyJs() or minifyCss().
*
* #var string
*/
public static $jarFile = null;
/**
* Writable temp directory. This must be set before calling minifyJs()
* or minifyCss().
*
* #var string
*/
public static $tempDir = null;
/**
* Filepath of "java" executable (may be needed if not in shell's PATH)
*
* #var string
*/
public static $javaExecutable = 'java';
/**
* Minify a Javascript string
*
* #param string $js
*
* #param array $options (verbose is ignored)
*
* #see http://www.julienlecomte.net/yuicompressor/README
*
* #return string
*/
public static function minifyJs($js, $options = array())
{
return self::_minify('js', $js, $options);
}
/**
* Minify a CSS string
*
* #param string $css
*
* #param array $options (verbose is ignored)
*
* #see http://www.julienlecomte.net/yuicompressor/README
*
* #return string
*/
public static function minifyCss($css, $options = array())
{
return self::_minify('css', $css, $options);
}
private static function _minify($type, $content, $options)
{
self::_prepare();
if (! ($tmpFile = tempnam(self::$tempDir, 'yuic_'))) {
throw new Exception('Minify_YUICompressor : could not create temp file.');
}
file_put_contents($tmpFile, $content);
exec(self::_getCmd($options, $type, $tmpFile), $output);
unlink($tmpFile);
return implode("\n", $output);
}
private static function _getCmd($userOptions, $type, $tmpFile)
{
$o = array_merge(
array(
'charset' => ''
,'line-break' => 5000
,'type' => $type
,'nomunge' => false
,'preserve-semi' => false
,'disable-optimizations' => false
)
,$userOptions
);
$cmd = self::$javaExecutable . ' -jar ' . escapeshellarg(self::$jarFile)
. " --type {$type}"
. (preg_match('/^[a-zA-Z0-9\\-]+$/', $o['charset'])
? " --charset {$o['charset']}"
: '')
. (is_numeric($o['line-break']) && $o['line-break'] >= 0
? ' --line-break ' . (int)$o['line-break']
: '');
if ($type === 'js') {
foreach (array('nomunge', 'preserve-semi', 'disable-optimizations') as $opt) {
$cmd .= $o[$opt]
? " --{$opt}"
: '';
}
}
return $cmd . ' ' . escapeshellarg($tmpFile);
}
private static function _prepare()
{
if (! is_file(self::$jarFile)) {
throw new Exception('Minify_YUICompressor : $jarFile('.self::$jarFile.') is not a valid file.');
}
if (! is_dir(self::$tempDir)) {
throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not a valid direcotry.');
}
if (! is_writable(self::$tempDir)) {
throw new Exception('Minify_YUICompressor : $tempDir('.self::$tempDir.') is not writable.');
}
}
}
Have you tried not using the --line-break option?
When I use YUI compressor I don't specify that option and the output is on a single line.
Judging from the source code you provided wherever you call
Minify_YUICompressor::minifyCss('/path/to.css');
You need to set the line-break option to -1 like this:
Minify_YUICompressor::minifyCss('/path/to.css', array('line-break' => -1));
put the following code at the beginning of you php script
<?php header('Content-Type:application/javascript'); ?>