My requirement is to restrict a content element with IP of a specific country (Eg: Austria). That means people visiting the website from Austrian IPs should be visible the content element and for all other users, it should be hidden. I am using geoip solution to check the country. I wrote a user function to implement this feature. I wrote a small extension and set hidden flag 1 and 0 based on countries. But due to TYPO3 caching, I want to clear the cache everytime to reflect the changes in frontend. I included the extension as USER_INT, and extension is non-cachable. But unfortunately not working. Functionality working, but due to caching changes not reflect in realtime.
$uid = 175; // uid of the content element needs to be hidden
$geoplugin = new \geoPlugin();
$geoplugin->locate();
$countryCode = $geoplugin->countryCode;
if( $countryCode == 'AT' ){
$GLOBALS['TYPO3_DB']->exec_UPDATEquery('tt_content', 'uid IN ('.$uid.')', array('hidden' => 0));
}else{
$GLOBALS['TYPO3_DB']->exec_UPDATEquery('tt_content', 'uid IN ('.$uid.')', array('hidden' => 1));
}
Is there any method available in TYPO3 to restrict content element for specific IP / Countries? or can you guys suggest a solution to fix this please?
The solution of Jost is much less dirty than hiding the element in the database depending on the visitors country. By your way the database probably changed on every user visit.
Just create a micro extension.
Related
On our website at www.EllasBubbles.com, we are using a functions.php script to execute an alternative stylesheet to users who are outside of U.S/Canada. This script is as follows:
// [International] - Dark Mode
add_action( 'wp_head' , 'custom_inline_css', 200 );
function custom_inline_css() {
// Get an instance of the WC_Geolocation object class
$geolocation_instance = new WC_Geolocation();
// Get user IP
$user_ip_address = $geolocation_instance->get_ip_address();
// Get geolocated user IP country code.
$user_geolocation = $geolocation_instance->geolocate_ip( $user_ip_address );
// For all countries except 'US'
if($user_geolocation['country'] !== 'US' && $user_geolocation['country'] !== 'CA'){
?>
<style>
<?php include 'international.php'; ?>
</style>
<?php
}
}
We use cloud flare to manage our Cache. I have properly setup bypass rules for these two files:
ellasbubbles.com/wp-content/themes/flatsome/international.php
ellasbubbles.com/wp-content/themes/flatsome/assets/css/flatsome.css
When loading the site from an international VPN, the "Dark Mode" (Outside U.S/Canada) version is displayed. However, when disabling the VPN; we are stuck on Dark Mode. Which is a bypassed file with Cloudflare Cache - and simply makes no sense to me.
This leads me to believe that the instance of the WC_Geolocation class is being cached somewhere on the Wordpress website. I have searched everywhere for a solution, and can not determine the best way to perform this custom CSS per country. Can we disable caching from function custom_inline_css ? Should I change international.php to css? Is there a better way to go about this?
Update 1: When I disabled caching from the entire website in cloud flare, this works fine!
Update 2: When I disable caching from everything inside ellasbubbles.com/wp-content/*; this still does not work properly..what file am I missing?
Update 3: I disabled all folders one by one to no avail
Please help me help everyone
I'm building a feature into a Laravel 5 app that will allow you to set the content of a status banner that will display across the top of the page. We will be using this banner both to display page-specific things (status messages, etc) and site-wide announcements (every user sees the same thing, banner stays the same for awhile).
Right now, I've implemented this by using Laravel sessions to allow banners to be added by calling a helper method from any controller or middleware:
// Call set_banner from in a controller or middleware (for persistent banners)
function set_banner($banner_text, $banner_class, $banner_persistant=false, $replace=false)
{
$banners = session()->get('banners', []);
// Create new banner
$banner = [
'text' => $banner_text,
'type' => $banner_class,
'persistent' => $banner_persistant
];
// Only put banner in array if it's not already there
if( !in_array($banner, $banners) ) {
// Either override existing banners, or add to queue
if( !$replace ) session()->push('banners', $banner);
else session()->put('banners', [$banner]);
}
}
// Called by default in the master.blade.php template
function get_banners()
{
$banners = session()->pull('banners', Array());
foreach( $banners as $banner ) {
// Print out each banner
print '<div class="col-md-12"><div class="text-center alert alert-block alert-'.$banner['type'].'">';
print $banner['text'];
print '</div></div>';
// Push back into the session if banner is marked as persistent
if ( $banner['persistent'] ) session()->push( 'banners', $banner );
}
}
Banners are created in controllers or middleware like this:
set_banner("<b>Note:</b> This is a sample persistant-scope banner set in a controller", "success", true);
Is there a better way to accomplish storing both page-level and site-wide banners? My concerns is that hitting the session on every pageload may be inefficient, especially for banners that won't be changing for long periods of time. Will this approach mess with Laravel's cache, etc?
As you said the banners do not change that often. Hence for me i would implement it using Cache. This improves performance since we need only one use to have the banners cached. And for the rest its retrieved faster from the Cache rather Session.
Do you want to have to change code to change the banner of a given page?
I would suggest instead creating a "pages" package, where each page route name is entered into a database.
From there, from your page service provider you get Page::getModel()->banner_text or something similar.
The method would look for a db result matching the current route name with a result within db.
when a controller method is triggered you simply call
Page::getBannerText()
That method will pull the current route name, pull the page result related to that page if it exists or create it if it does not exist (easy way to get everything). You cache the db query result for X hours, days or whatever so whenever someone else makes a call, you don't even need to deal with any storage on client side.
This allows you to modify the value from a db fascet. Its the more "proper" way to do it.
We are planned to host a single CMS for the multiple sites.
Is there are way in YII we can do that, The idea is simple we want to share single application and single database for all the domains but we will let them choose the different themes for the different website.
By website I mean totally different Domains.
What other setting will we have to do to point all the domains to single server ?
Edit::
I don't want the different serve directory for each domain. what I want to do it, keep the installation only one.
i.e.
/server/www/master
then all the domains
a.com, b.com, c.com read the same dir "/server/www/master" and same DB. and records get filer on the base of site.
I have done exactly that with Yii so yes it is possible.
In your Apache settings make sure to point all the domain names to the same directory (using ServerAlias - http://httpd.apache.org/docs/2.2/mod/core.html#serveralias).
In my database I created a table with a row for each website, storing the domain name as one of the fields.
In my ApplicationConfigBehavior.php::beginRequest (which is executed for every request), I did something like this:
/**
* Load configuration that cannot be put in config/main
*/
public function beginRequest()
{
if(empty(Yii::app()->session['community'])){
$current_community = Community::model()->with(array(
'communityHosts'=>array(
'joinType'=>'INNER JOIN',
'condition'=>'`communityHosts`.hostname= :hostname',
'params' => array(':hostname' => $_SERVER['SERVER_NAME'])
),
))->find();
Yii::app()->session['community'] = serialize($current_community);
}
else{
$current_community = unserialize(Yii::app()->session['community']);
}
if(!empty($current_community)){
Yii::app()->name = $current_community->name;
Yii::app()->params['currentCommunity'] = $current_community;
Yii::app()->language = $current_community->language;
}
else{
//TODO: Throw error
session_unset();
die('Hostname ' . $_SERVER['SERVER_NAME'] .' not found');
}
}
Which basically says, looks for this server name in my database, get the current "community" (my sites), and store all the settings (theme, site name, etc...) in the session.
The exact query might not be the same for you. It's just to give you the general idea. Adapt it to your database schema or however you store the settings for each website.
In the apache virtual host file, set the site name
SetEnv SITE_NAME "CMSA"
Get site name in the code using
defined('SITE_NAME') || define('SITE_NAME', ( getenv('SITE_NAME') );
Use the constant in the config and filter your records based on the site.
The same way theme can also be declared.
I'm trying to create configurable products programmatically in Magento 1.5.1.
I understand I need first to create simple related products, what I did. Now I manage to associate these simple products to make a configurable one.
Here is the critical part...
I keep the ids and some of the attributes values in an array, so I can later make my configurable product, but some of them are missing, I don't know which method to call.
I found this entry in Magento Wiki, that helped me and seems to fit my needs.
However, at the end the author is setting two things :
$product->setConfigurableProductsData($data);
$product->setConfigurableAttributesData($data);
and the values in the arrays have been taken in the admin page source using Firebug....and then translated into PHP arrays (array example for the first call) :
"I’ve harcoded the values for my associated products and attribute
data. You can get attribute data by viewing the source through the
admin interface and using Firebug for Firefox."
$data = array('5791'=>array('0'=>array('attribute_id'=>'491', // I already got this
'label'=>'vhs', // this too
'value_index'=>'5', // but what is value_index ?
'is_percent'=>0,
'pricing_value'=>'')),
'5792'=>array('0'=>array('attribute_id'=>'491',
'label'=>'dvd',
'value_index'=>'6',
'is_percent'=>0,
'pricing_value'=>'')));
My question is : is there a way to retrieve these values without using Firebug (which in my script won't help me a lot !), but programmatically. I already found a way to retrieve attribute values, labels, etc... using its code, but one field I don't know is value_index.
I guess this may be the option position in an option list, but not sure.
Also if someone knows a good/better way to create a configurable product in Magento, please tell me.
Any help is welcome thank you.
It seems you're asking where to retrieve the value_index value where you already have the label. Here's what I had: I didn't test this on 1.5x.
function get_attribute_id($option, $type) {
$attributeId = Mage::getResourceModel('eav/entity_attribute')->getIdByCode('catalog_product', $type);
$attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
$attributeOptions = $attribute->getSource()->getAllOptions();
foreach ($attributeOptions as $opts_arr) {
if (strtoupper($opts_arr['label']) == strtoupper($option)) {
return $opts_arr['value'];
}
}
return FALSE;
}
$value_index = get_attribute_id('vhs', 'media_format');
No one else seemed to mention the easiest way to figure out what the value_index of vhs is: In the backend, under
Catalog > Manage > media_format > Manage Label/Options
Inspect the source of the individual form inputs. Where you have 'vhs' you should have an input named option[value][6]
As far as I understand your question, there are two options: a) create simple products by script, put the generated id's in an array and create the configurables using the ids or b) read the id's from the admin and put them in your script. Since programming is about automation I'd definately go for option a.
Going a bit mad here... :)
I'm just trying to add CCK fields from a Content Profile content type into page-user.tpl.php (I'm creating a highly-themed user profile page).
There seem to be two methods, both of which have a unique disadvantage that I can't seem to overcome:
'$content profile' method.
$var = $content_profile->get_variables('profile');
print $var['field_last_name'][0]['safe'];
This is great, except I can't seem to pass the currently viewed user into $content_profile, and it therefore always shows the logged in user.
'$content profile load' method.
$account_id = arg(1);
$account = user_load($account_id);
$user_id = $account->uid;
$var = content_profile_load('profile', $user_id);
print $var->field_first_name[0]['value'];
Fine, but now I can't access the full rendered fields, only the plain values (i.e. if the field has paragraphs they won't show up).
How can I have both things at once? In other words how can I show fields relating to the currently viewed user that are also rendered (the 'safe' format in 1)?
I've Googled and Googled and I just end up going round in circles. :(
Cheers,
James
Your content profile load method seems to be the closest to what you want.
In your example:
$account_id = arg(1);
$account = user_load($account_id);
$user_id = $account->uid;
$var = content_profile_load('profile', $user_id);
print $var->field_first_name[0]['value'];
The $var is just a node object. You can get the "full rendered fields" in a number of ways (assuming you mean your field with a filter applied).
The most important thing to check is that you're field is actually configured properly.
Go to:
admin/content/node-type/[node-type]/fields/field_[field-name] to configure your field and make sure that under text processing that you've got "Filtered text" selected.
If that doesn't fix it,try applying this:
content_view_field(content_fields("field_last_name"), $var, FALSE, FALSE)
(more info on this here: http://www.trevorsimonton.com/blog/cck-field-render-node-formatter-format-output-print-echo )
in place of this:
print $var->field_first_name[0]['value'];
if none of that helps... try out some of the things i've got on my blog about this very problem:
http://www.trevorsimonton.com/blog/print-filtered-text-body-input-format-text-processing-node-template-field-php-drupal
When you're creating a user profile page there is a built in mechanism for it. just create a user template file, user_profile.tpl.php.
When you use the built in mechanism you automatically get access to the $account object of the user you are browsing, including all user profile cck fields. You have the fields you are looking for without having to programmatically load the user.
I have a field called profile_bio and am able to spit out any mark up that is in without ever having to ask for the $account.
<?php if ($account->content[Profile][profile_bio]['#value']) print "<h3>Bio</h3>".$account->content[Profile][profile_bio]['#value']; ?>
I've tried themeing content profiles by displaying profile node fields through the userpage before and it always seems a little "hacky" to me. What I've grown quite fond of is simply going to the content profile settings page for that node type and setting the display to "Display the full content". This is fine and dandy except for the stupid markup like the node type name that content profile injects.
a solution for that is to add a preprocess function for the content profile template. one that will unset the $title and remove the node-type name that appears on the profile normally.
function mymodule_preprocess_content_profile_display_view(&$variables) {
if ($variables['type'] == 'nodetypename') {
unset($variables['title']);
}
}
A function similar to this should do the trick. Now to theme user profiles you can simply theme your profile nodes as normal.