Exchange Web Service get Public Subfolder with PHP-EWS - php

I'm using PHP-EWS (https://github.com/jamesiarmes/php-ews) inside a cakePHP application. The goal is to read E-Mails from a "Public Folder" from the exchange server.
The Problem is I can only read the first "Dimension" of public folders and can't find a way to get the subdirectorys.
The folder I have to read from is 4 levels deep.
$this->connect();
// start building the find folder request
$request = new FindFolderType();
$request->Traversal = FolderQueryTraversalType::SHALLOW;
$request->FolderShape = new FolderResponseShapeType();
$request->FolderShape->BaseShape = DefaultShapeNamesType::ALL_PROPERTIES;
// configure the view
$request->IndexedPageFolderView = new IndexedPageViewType();
$request->IndexedPageFolderView->BasePoint = 'Beginning';
$request->IndexedPageFolderView->Offset = 0;
// set the starting folder
$request->ParentFolderIds = new NonEmptyArrayOfBaseFolderIdsType();
$request->ParentFolderIds->DistinguishedFolderId = new DistinguishedFolderIdType();
$request->ParentFolderIds->DistinguishedFolderId->Id = DistinguishedFolderIdNameType::PUBLIC_FOLDERS_ROOT;
// request
$response = $this->ews->FindFolder($request);
If I change "Traversal" to DEEP I get the error .
DEEP TRAVERSAL queries are not allowed for public folders.
I also tried to change
$request->IndexedPageFolderView->BasePoint
To things like "end" "second", it didn't change anything so I could not figure out what it does and how to use it.
I can't get the subdirectory Folder id (for changing the start point) either because it gets never selected.
Thank you for your help.

Very good question. Unfortunately the library that you've chosen is out of date and unmaintained. I personally would suggest you use my more up to date one, garethp/php-ews.
I don't know if this is the best solution, but what I would suggest is to get the first level folder, then the second and so on. So if you know the directory structure of your folders, and it looked something like this
- Folder 1
- Subfolder 1
- Subfolder 2
- Subfolder 3 (Target)
- Folder 2
- Folder 3
Then first you'd get Folder 1, which would be a child of DistinguishedFolderIdNameType::PUBLIC_FOLDERS_ROOT. Then you would get Subfolder 1 which would be a child of Folder 1, then get Subfolder 2, then Subfolder 3. I can't advise you on how you would manage that with the library you're currently using, but with mine it would look something like
$api = MailAPI::withUsernameAndPassword($host, $username, $password);
$folder1 = $api->getFolderByDisplayName('Folder1', Enumeration\DistinguishedFolderIdNameType::PUBLICFOLDERSROOT);
$subFolder1 = $api->getFolderByDisplayName('Subfolder1', $folder1->getFolderId());
$subFolder2 = $api->getFolderByDisplayName('Subfolder2', $subfolder1->getFolderId());
$subFolder3 = $api->getFolderByDisplayName('Subfolder3', $subfolder2->getFolderId());
$api->setFolderId($subFolder3->getFolderId());
Obviously that's a lot of calls, so if you're using that folder ID often, I would save the FolderID to a database for quicker retrieval later

Related

How to clone ImageAd and ResponsiveDisplayAd

We need to update finalUrls of all the ads we have. We have several hundred ImageAd and ResponsiveDisplayAds and we don't want to lose the existing configuration and/or images. As Google doesn't allow us to update any property of a AdGroupAd apart from status, we will have to clone them using ADD operator.
While doing this we get several errors and all of them are related to ad.image. What's the correct/best way to go about these updates?
[AdError.IMAGE_ERROR # operations[0].operand.ad]
Firstly, I found out from little googling that adToCopyImageFrom is what I had to use in order to copy over image properties of an ad (ImageAd only!) in order to clone. So, if $currentAd is the AdGroupAd object containing your existing ImageAd and you are trying to create a new one $newAd and want to copy over images, here is what you can do (not sure if this is the best way but worked well for me!):
$newAd = new ImageAd();
$newAd = $ad->ad;
// Let Google do the image copying
// Remember $currentAd is a AdGroupAd and not an Ad
$newAd->adToCopyImageFrom = $currentAd->ad->id;
$newAd->id = null;
$newAd->image = null;
Similarly, for ResponsiveDisplayAd, here is what I did:
$newRespAd = new ResponsiveDisplayAd();
// Make sure you included MediaId while fetching
// $currentRespAd
$newRespAd = $currentRespAd->ad;
$newRespAd->id = null;

Magento load modules by website/store

I'm working on a webiste that has one store already live and I'm trying to make the second store/website working.
The new website has a template that includes some observers that even if I disable the modules through System -> Configuration -> Advanced as this this only Disable Modules Output not the actual module, therefore if there are any Observers they will still be loaded and will run.
Searched online and didn't found a complete solution for this. On this other post the user Eric Hainer proposed a solution to that allows to load modules depending checking the $_SERVER['MAGE_RUN_CODE'] variable but this does not work if you have cache active as when you load the store that has the modules in it will put them in the cache.
So my solution was to modify the file
app/code/core/Mage/Core/Model/Config/Options.php to save the cache on different folders depending on the store
First I copied the file to app/code/local/Mage/Core/Model/Config/Options.php to avoid changing a core file
and on the constructor added this lines
//custom code to save cache on different folders per website
$runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');
$this->_data['cache_dir'] = $this->_data['var_dir'].DS.'cache'.$runCode;
Here is how the constructor looks like
protected function _construct()
{
$appRoot= Mage::getRoot();
$root = dirname($appRoot);
$this->_data['app_dir'] = $appRoot;
$this->_data['base_dir'] = $root;
$this->_data['code_dir'] = $appRoot.DS.'code';
$this->_data['design_dir'] = $appRoot.DS.'design';
$this->_data['etc_dir'] = $appRoot.DS.'etc';
$this->_data['lib_dir'] = $root.DS.'lib';
$this->_data['locale_dir'] = $appRoot.DS.'locale';
$this->_data['media_dir'] = $root.DS.'media';
$this->_data['skin_dir'] = $root.DS.'skin';
$this->_data['var_dir'] = $this->getVarDir();
$this->_data['tmp_dir'] = $this->_data['var_dir'].DS.'tmp';
//custom code to save cache on different folders per website
$runCode = (isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : 'default');
$this->_data['cache_dir'] = $this->_data['var_dir'].DS.'cache'.$runCode;
$this->_data['log_dir'] = $this->_data['var_dir'].DS.'log';
$this->_data['session_dir'] = $this->_data['var_dir'].DS.'session';
$this->_data['upload_dir'] = $this->_data['media_dir'].DS.'upload';
$this->_data['export_dir'] = $this->_data['var_dir'].DS.'export';
}
This will do the job but there are some issues:
Clear cache will probably not work
Updates will not be applied automatically as we copied this files from core
Is there any other way to do this?
This post continues here
Disable the module output per store in the backend under advanced. Then edit your module observer functions and check for that configuration to disable the complete module functionality:
if(Mage::getStoreConfigFlag('advanced/modules_disable_output/YOUR_MODULE'))
return false;
Most community modules already have it's own configuration to enable/disable functionality per store.

Is there a way we can build YII multisite application with one database for multiple domains

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.

Adding a node programmatically

I am very new to Drupal. I need to develop a site using this CMS. I can understand creating content as an admin. But I would like to create content from code. For example I want to create articles in the backend programmatically without publishing them. So that site admin can review and publish them if he wants to. Tasks like these.Are there any references for programmers? About the structure of drupal code and where to write what things like that. Not videos I can't watch them in office.
Custom code in Drupal is generally done with the help of modules.
One way to familiarize yourself with the Drupal API could be to install the Examples.
In your Google searches, go for tutorials about writing your own modules.
THis being said, saving a node programmatically is fairly straightforward & I doubt you will have problems finding out how to do it.
Your main problem is to understand the "Drupal Way".
You can check excellent resources such as
- buildamodule.com
- drupalize.me
SOLUTION !
You can use below code to create a node programatically with drupal,
$node = new stdClass(); // Create a new node object
$node->type = 'YOUR_CONTENT_TYPE';
node_object_prepare($node); // Set some default values
$node->language = LANGUAGE_NONE;
$node->status = 0; // un-published
$node->uid = 'USER_ID';
$node->title = 'YOUR_TITLE';
$node->body['und'][0]['value'] = 'YOUR_DESCRIPTION';
$node->body['und'][0]['summary'] = 'YOUR_SHORT_DESCRIPTION';
$node->body['und'][0]['format'] = 'filtered_html';
$node = node_submit($node); //prepare node for saving
node_save($node); // save node

Google Docs API - Zend gData - How to find the URI of a collection

I have an entry of type Zend_Gdata_App_Entry,
This entry is a collection/folder and i try to get the URI of this folder,
I know that the URI is an URL but the id of the entry is an URL also so what is the difference?
I would like to do this :
// Instantiate a FolderQuery object to retrieve the content of the folder.
FolderQuery contentQuery = new FolderQuery(folder.ResourceId);
URI = contentQuery.Uri
But not in .NET but using the Zend gdata framework in PHP
Thank you !
In GData the self URI and the ID are relatively similar usually. So if you have one or the other it really doesn't matter much.
The ResourceID is a little different since they are not URLs but are in the form folder:1234. They can be easily constructed if you have the number after the folder: prefix. If you look closely the ID of the document cis constructed from the resource ID. There are on practical differences for all these, they are mostly needed by the GData protocol.
Anyways, once you have the ID or the ressource ID of the folder you cold list its content by using the following URL:
https://docs.google.com/feeds/default/private/full/folder%3A1234/contents
Just make sure you replace folder%3A1234 with he actual Ressource ID of the folder.
Then you could use that URL in the method Zend_Gdata_Docs.getDocumentListFeed(String location) as the location attribute. That will get you a Document Feed containing all the elements inside the folder.
Maybe this will help you. Creating subfolder and then upload file to a new folder:
$service = Zend_Gdata_Docs::AUTH_SERVICE_NAME;
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $service);
$docs = new Zend_Gdata_Docs($client);
$parentFolder = 'folder%3A[folderid]';
$newFolder = $docs->createFolder($_POST['email'], $parentFolder);
$location = str_replace($parentFolder . '/', '', $newFolder->getSelfLink()->getHref());
// Upload the file to google docs
$newDocumentEntry = $docs->uploadFile(
$fileToUploadTemp,
$fileToUpload,
Zend_Gdata_Docs::lookupMimeType($fileExtension),
$location
);

Categories