Trying to get and set array data inside an object - drupal-8

I'm trying to extract (and set) from the screenshot below the conf->folders inside profile array. I am able to access other things such as "id" using $profile->id(). I tried what was suggested in other SO questions " $profile->conf['folders'] " which fails.
$folders = array();
$some_settings = \Drupal::config('some.settings');
foreach ($ids as id) {
$profile = $storage->load($some_settings[$id]);
$folders[] = $profile->conf['folders']; // Fails to get array
}
When finished want to reset the value to something (much like this):
$profile->conf['folders'] = $folders;

I seemed to have figured it out, I am new to Drupal programming but it seems I can do the following:
$folders = array();
$some_settings = \Drupal::config('some.settings');
foreach ($ids as id) {
$profile = $storage->load($some_settings[$id]);
$folders[] = $p->get('conf')['folders'];
}
// In following, $profile->set('conf.folders', $folders); should have worked instead, instead resigned 'conf' instead of just 'folders'.
$conf = $profile->get('conf');
$conf["folders"] = $folders;
$profile->set('conf', $conf);
Parsed from documents such as this:
https://www.drupal.org/docs/8/api/entity-api/working-with-the-entity-api

Related

How to call AWS Cloudfront Update-CFDistribution Powershell Cmdlet

I have written the script to change the origin path" of a specific origin on a specific distribution in CloudFront. After changing the path I am getting errors when trying to update the distribution with the changes. I do not want to change anything else on the distribution besides the "origin path", so how do I call Update-CFDistribution to make these changes ideally without having to set every parameter (future updates to the API may cause this script to fail or even worst make incomplete modifications)?
$distributions = Get-CFDistributionList
foreach($distribution in $distributions) {
if($distribution.Id -eq "$CloudfrontDistributionId") {
foreach ($origin in $distribution.Origins) {
foreach($item in $origin.Items) {
if($item.Id -eq "OriginName") {
$item.OriginPath = "/$($S3BucketPrefix)"
Update-CFDistribution -Id $CloudfrontDistributionId -Origins_Item #($item)
}
}
}
}
}
Error
InvalidOperation: 5 validation errors detected: Value null at
'distributionConfig.defaultCacheBehavior' failed to satisfy
constraint: Member must not be null; Value null at
'distributionConfig.enabled' failed to satisfy constraint: Member must
not be null; Value null at 'distributionConfig.callerReference' failed
to satisfy constraint: Member must not be null; Value null at
'distributionConfig.origins.quantity' failed to satisfy constraint:
Member must not be null; Value at 'distributionConfig.comment' failed
to satisfy constraint: Member must not be null
I don't have the reputation to add just a comment so I'm having to put this as an answer, but it's better suited as a comment.
According to the documentation, there are a number of required fields when you issue an update, even if you're only trying to update one thing:
https://docs.aws.amazon.com/powershell/latest/reference/items/Update-CFDistribution.html
When you update a distribution, there are more required fields than
when you create a distribution. When you update your distribution by
using this API action, follow the steps here to get the current
configuration and then make your updates, to make sure that you
include all of the required fields.
I had the same issue and asked about it on the aws-tools-for-powershell Q&A. As far as I can tell, the answer is you just have to map all the properties. I took the time to do that today. In other PowerShell module contexts, I would expect you'd be able to just pipe in the object from a Get call with changes into an Update call and it would handle the parameter bindings. That doesn't work in this context. This is a known issue for a lot of aws-tools-for-powershell cmdlets according to aws-tools-for-powershell Issue #214.
Below is a snippet of the 66 mappings required to ensure you're updating all properties exactly as they were handed to you in the original Get call. It's possible fewer are actually required, but given I want an exact copy it felt safer to ensure all the data was available and let the API decide what could be dropped.
The etag thing is from: AWS PowerShell update CloudFront distribution
$distribution = Get-CFDistribution -Id $distributionFromList.Id
$etag = $AWSHistory.LastServiceResponse.ETag
$params = #{
Id = $distribution.Id
Verbose = $true
IfMatch = $etag
Aliases_Item = $distribution.DistributionConfig.Aliases.Items
Aliases_Quantity = $distribution.DistributionConfig.Aliases.Quantity
AllowedMethods_Item = $distribution.DistributionConfig.DefaultCacheBehavior.AllowedMethods.Items
AllowedMethods_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.AllowedMethods.Quantity
CacheBehaviors_Item = $distribution.DistributionConfig.CacheBehaviors.Items
CacheBehaviors_Quantity = $distribution.DistributionConfig.CacheBehaviors.Quantity
CachedMethods_Item = $distribution.DistributionConfig.DefaultCacheBehavior.AllowedMethods.CachedMethods.Items
CachedMethods_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.AllowedMethods.CachedMethods.Quantity
Cookies_Forward = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.Cookies.Forward
CustomErrorResponses_Item = $distribution.DistributionConfig.CustomErrorResponses.Items
CustomErrorResponses_Quantity = $distribution.DistributionConfig.CustomErrorResponses.Quantity
DefaultCacheBehavior_CachePolicyId = $distribution.DistributionConfig.DefaultCacheBehavior.CachePolicyId
DefaultCacheBehavior_Compress = $distribution.DistributionConfig.DefaultCacheBehavior.Compress
DefaultCacheBehavior_DefaultTTL = $distribution.DistributionConfig.DefaultCacheBehavior.DefaultTTL
DefaultCacheBehavior_FieldLevelEncryptionId = $distribution.DistributionConfig.DefaultCacheBehavior.FieldLevelEncryptionId
DefaultCacheBehavior_MaxTTL = $distribution.DistributionConfig.DefaultCacheBehavior.MaxTTL
DefaultCacheBehavior_MinTTL = $distribution.DistributionConfig.DefaultCacheBehavior.MinTTL
DefaultCacheBehavior_OriginRequestPolicyId = $distribution.DistributionConfig.DefaultCacheBehavior.OriginRequestPolicyId
DefaultCacheBehavior_RealtimeLogConfigArn = $distribution.DistributionConfig.DefaultCacheBehavior.RealtimeLogConfigArn
DefaultCacheBehavior_ResponseHeadersPolicyId = $distribution.DistributionConfig.DefaultCacheBehavior.ResponseHeadersPolicyId
DefaultCacheBehavior_SmoothStreaming = $distribution.DistributionConfig.DefaultCacheBehavior.SmoothStreaming
DefaultCacheBehavior_TargetOriginId = $distribution.DistributionConfig.DefaultCacheBehavior.TargetOriginId
DefaultCacheBehavior_ViewerProtocolPolicy = $distribution.DistributionConfig.DefaultCacheBehavior.ViewerProtocolPolicy
DistributionConfig_CallerReference = $distribution.DistributionConfig.CallerReference
DistributionConfig_Comment = $distribution.DistributionConfig.Comment
DistributionConfig_DefaultRootObject = $distribution.DistributionConfig.DefaultRootObject
DistributionConfig_Enabled = $distribution.DistributionConfig.Enabled
DistributionConfig_HttpVersion = $distribution.DistributionConfig.HttpVersion
DistributionConfig_IsIPV6Enabled = $distribution.DistributionConfig.IsIPV6Enabled
DistributionConfig_PriceClass = $distribution.DistributionConfig.PriceClass
DistributionConfig_WebACLId = $distribution.DistributionConfig.WebACLId
ForwardedValues_QueryString = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.QueryString
FunctionAssociations_Item = $distribution.DistributionConfig.DefaultCacheBehavior.FunctionAssociations.Items
FunctionAssociations_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.FunctionAssociations.Quantity
GeoRestriction_Item = $distribution.DistributionConfig.Restrictions.GeoRestriction.Items
GeoRestriction_Quantity = $distribution.DistributionConfig.Restrictions.GeoRestriction.Quantity
GeoRestriction_RestrictionType = $distribution.DistributionConfig.Restrictions.GeoRestriction.RestrictionType
Headers_Item = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.Headers.Items
Headers_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.Headers.Quantity
LambdaFunctionAssociations_Item = $distribution.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.Items
LambdaFunctionAssociations_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.LambdaFunctionAssociations.Quantity
Logging_Bucket = $distribution.DistributionConfig.Logging.Bucket
Logging_Enabled = $distribution.DistributionConfig.Logging.Enabled
Logging_IncludeCookie = $distribution.DistributionConfig.Logging.IncludeCookies
Logging_Prefix = $distribution.DistributionConfig.Logging.Prefix
OriginGroups_Item = $distribution.DistributionConfig.OriginGroups.Items
OriginGroups_Quantity = $distribution.DistributionConfig.OriginGroups.Quantity
Origins_Item = $distribution.DistributionConfig.Origins.Items
Origins_Quantity = $distribution.DistributionConfig.Origins.Quantity
QueryStringCacheKeys_Item = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.QueryStringCacheKeys.Items
QueryStringCacheKeys_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.QueryStringCacheKeys.Quantity
TrustedKeyGroups_Enabled = $distribution.DistributionConfig.DefaultCacheBehavior.TrustedKeyGroups.Enabled
TrustedKeyGroups_Item = $distribution.DistributionConfig.DefaultCacheBehavior.TrustedKeyGroups.Items
TrustedKeyGroups_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.TrustedKeyGroups.Quantity
TrustedSigners_Enabled = $distribution.DistributionConfig.DefaultCacheBehavior.TrustedSigners.Enabled
TrustedSigners_Item = $distribution.DistributionConfig.DefaultCacheBehavior.TrustedSigners.Items
TrustedSigners_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.TrustedSigners.Quantity
ViewerCertificate_ACMCertificateArn = $distribution.DistributionConfig.ViewerCertificate.ACMCertificateArn
ViewerCertificate_Certificate = $distribution.DistributionConfig.ViewerCertificate.Certificate
ViewerCertificate_CertificateSource = $distribution.DistributionConfig.ViewerCertificate.CertificateSource
ViewerCertificate_CloudFrontDefaultCertificate = $distribution.DistributionConfig.ViewerCertificate.CloudFrontDefaultCertificate
ViewerCertificate_IAMCertificateId = $distribution.DistributionConfig.ViewerCertificate.IAMCertificateId
ViewerCertificate_MinimumProtocolVersion = $distribution.DistributionConfig.ViewerCertificate.MinimumProtocolVersion
ViewerCertificate_SSLSupportMethod = $distribution.DistributionConfig.ViewerCertificate.SSLSupportMethod
WhitelistedNames_Item = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.Cookies.WhitelistedNames.Items
WhitelistedNames_Quantity = $distribution.DistributionConfig.DefaultCacheBehavior.ForwardedValues.Cookies.WhitelistedNames.Quantity
}
Update-CFDistribution #params -WhatIf

How to add hyperlink using templateprocessor (PHPWord Library)

I want to replace email variable into a hyperlink using template processor and I have used two way to solved this issue but didn't work and here is our below code for replacing email variable into hyperlink but when I used setValue or setComplexValue function for replacement value then document is corrupted.
We have tried below two scenarios for adding hyperlink but didn't work for us.
1. First Way
$pw = new \PhpOffice\PhpWord\PhpWord();
$section = $pw->addSection();
$textrun = $section->addTextRun();
$textrun->addTextBreak(2);
$section->addLink('mailto:demo1#gmail.com?subject=DEMO','demo1#gmail.com', array('color' => 'FF0000', 'underline' =>
\PhpOffice\PhpWord\Style\Font::UNDERLINE_SINGLE));
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($pw, 'Word2007');
$fullXml = $objWriter->getWriterPart('Document')->write();
$templateProcessor->setValue($var, $this->getBodyBlock($fullXml));
2. Second Way
$pw = new \PhpOffice\PhpWord\PhpWord();
$section = $pw->addSection();
$convertResult = 'demo1#gmail.com';
\PhpOffice\PhpWord\Shared\Html::addHtml($section, $convertResult, false,false);
$objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($pw, 'Word2007');
$fullXml = $objWriter->getWriterPart('Document')->write();
$templateProcessor->setValue($var, $this->getBodyBlock($fullXml));
protected function getBodyBlock($string) {
if (preg_match('%(?i)(?<=<w:body>)[\s|\S]*?(?=</w:body>)%', $string, $regs)) {
return $regs[0];
} else {
return '';
}
}
Please help us thank in advance.

Magento: get a list of attribute values

I am new to Magento and I'm building a bookshop. I have an attribute called author, and I would like to show a list of all authors (a list of their attribute values). I tried to create a widget and use this code in it but it returns me an empty array. How can I achieve this? Where should I place the code, in a widget, a block?
protected function _toHtml()
{
$name='author';
$attributeInfo = Mage::getResourceModel('eav/entity_attribute_collection')->setCodeFilter($name)->getFirstItem();
$attributeId = $attributeInfo->getAttributeId();
$attribute = Mage::getModel('catalog/resource_eav_attribute')->load($attributeId);
$attributeOptions = $attributeInfo->getSource()->getAllOptions(false);
$html = '<ul>';
foreach($attributeOptions as $opt)
$html .= '<li>'.$opt[0].'</li>';
$html .= '</ul>';
return $html;
}
$attributes = $product->getAttributes();
foreach ($attributes as $attribute) {
if ($attribute->getIsVisibleOnFront()) {
$value = $attribute->getFrontend()->getValue($product);
echo $value
}
}
you can get attribute with this code just write this code in view.phtml
Thank you very much, your code worked quite good for a particular product, however i finally get what I wanted using this:
$attributeCode='author';
// build and filter the product collection
$products = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter($attributeCode, array('notnull' => true))
->addAttributeToFilter($attributeCode, array('neq' => ''))
->addAttributeToSelect($attributeCode);
// get all distinct attribute values
$usedAttributeValues = array_unique($products->getColumnValues($attributeCode));
sort($usedAttributeValues);

How do I query multiple IDs via the ContentSearchManager?

When I have an array of Sitecore IDs, for example TargetIDs from a MultilistField, how can I query the ContentSearchManager to return all the SearchResultItem objects?
I have tried the following which gives an "Only constant arguments is supported." error.
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(x => f.TargetIDs.Contains(x.ItemId));
rpt.DataBind();
}
I suppose I could build up the Linq query manually with multiple OR queries. Is there a way I can use Sitecore.ContentSearch.Utilities.LinqHelper to build the query for me?
Assuming I got this technique to work, is it worth using it for only, say, 10 items? I'm just starting my first Sitecore 7 project and I have it in mind that I want to use the index as much as possible.
Finally, does the Page Editor support editing fields somehow with a SearchResultItem as the source?
Update 1
I wrote this function which utilises the predicate builder as dunston suggests. I don't know yet if this is actually worth using (instead of Items).
public static List<T> GetSearchResultItemsByIDs<T>(ID[] ids, bool mustHaveUrl = true)
where T : Sitecore.ContentSearch.SearchTypes.SearchResultItem, new()
{
Assert.IsNotNull(ids, "ids");
if (!ids.Any())
{
return new List<T>();
}
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var predicate = PredicateBuilder.True<T>();
predicate = ids.Aggregate(predicate, (current, id) => current.Or(p => p.ItemId == id));
var results = s.GetQueryable<T>().Where(predicate).ToDictionary(x => x.ItemId);
var query = from id in ids
let item = results.ContainsKey(id) ? results[id] : null
where item != null && (!mustHaveUrl || item.Url != null)
select item;
return query.ToList();
}
}
It forces the results to be in the same order as supplied in the IDs array, which in my case is important. (If anybody knows a better way of doing this, would love to know).
It also, by default, ensures that the Item has a URL.
My main code then becomes:
var f = (Sitecore.Data.Fields.MultilistField) rootItem.Fields["Main navigation links"];
rpt.DataSource = ContentSearchHelper.GetSearchResultItemsByIDs<SearchResultItem>(f.TargetIDs);
rpt.DataBind();
I'm still curious how the Page Editor copes with SearchResultItem or POCOs in general (my second question), am going to continue researching that now.
Thanks for reading,
Steve
You need to use the predicate builder to create multiple OR queries, or AND queries.
The code below should work.
using (var s = Sitecore.ContentSearch.ContentSearchManager.GetIndex("sitecore_master_index").CreateSearchContext())
{
var predicate = PredicateBuilder.True<SearchResultItem>();
foreach (var targetId in f.Targetids)
{
var tempTargetId = targetId;
predicate = predicate.Or(x => x.ItemId == tempTargetId)
}
rpt.DataSource = s.GetQueryable<SearchResultItem>().Where(predicate);
rpt.DataBind();
}

Subsonic 3 Save() then Update()?

I need to get the primary key for a row and then insert it into one of the other columns in a string.
So I've tried to do it something like this:
newsObj = new news();
newsObj.name = "test"
newsObj.Save();
newsObj.url = String.Format("blah.aspx?p={0}",newsObj.col_id);
newsObj.Save();
But it doesn't treat it as the same data object so newsObj.col_id always comes back as a zero. Is there another way of doing this? I tried this on another page and to get it to work I had to set newsObj.SetIsLoaded(true);
This is the actual block of code:
page p;
if (pageId > 0)
p = new page(ps => ps.page_id == pageId);
else
p = new page();
if (publish)
p.page_published = 1;
if (User.IsInRole("administrator"))
p.page_approved = 1;
p.page_section = staticParent.page_section;
p.page_name = PageName.Text;
p.page_parent = parentPageId;
p.page_last_modified_date = DateTime.Now;
p.page_last_modified_by = (Guid)Membership.GetUser().ProviderUserKey;
p.Add();
string urlString = String.Empty;
if (parentPageId > 0)
{
urlString = Regex.Replace(staticParent.page_url, "(.aspx).*$", "$1"); // We just want the static page URL (blah.aspx)
p.page_url = String.Format("{0}?p={1}", urlString, p.page_id);
}
p.Save();
If I hover the p.Save(); I can see the correct values in the object but the DB is never updated and there is no exception.
Thanks!
I faced the same problem with that :
po oPo = new po();
oPo.name ="test";
oPo.save(); //till now it works.
oPo.name = "test2";
oPo.save(); //not really working, it's not saving the data since isLoaded is set to false
and the columns are not considered dirty.
it's a bug in the ActiveRecord.tt for version 3.0.0.3.
In the method public void Add(IDataProvider provider)
immediately after SetIsNew(false);
there should be : SetIsLoaded(true);
the reason why the save is not working the second time is because the object can't get dirty if it is not loaded. By adding the SetIsLoaded(true) in the ActiveRecord.tt, when you are going to do run custom tool, it's gonna regenerate the .cs perfectly.