How to create a <xhtml:link ... /> with DOMDocument - domdocument

The sitemap is created with DOMDocument and everything works fine. Now I want to create it multilingual. How can I create the xhtml:link element in the following code?
<url>
<loc>http://www.ihremusterdomain.de/english/</loc>
<xhtml:link rel="alternate" hreflang="de" href="http://www.ihremusterdomain.de/deutsch/" />
<lastmod>2014-04-15T16:13:34+02:00</lastmod>
<changefreq>daily</changefreq>
</url>
The other elements like url, loc, lastmod and changefreq yet exist.

In C#, you can do like:
var linkElement = document.CreateElement("xhtml:link", "http://www.w3.org/1999/xhtml");
You need to provide full qualified name along with namespace uri.

Because the node is in the XHTML namespace, you need to use createElementNS to add it:
<?php
$doc = new DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->load('sitemap.xml');
foreach ($doc->getElementsByTagName('loc') as $loc) {
$node = $doc->createElementNS('http://www.w3.org/1999/xhtml', 'xhtml:link');
$node->setAttribute('rel', 'alternate');
$node->setAttribute('hreflang', 'de');
$node->setAttribute('href', str_replace('english', 'deutsch', $loc->textContent));
if ($loc->nextSibling) {
$loc->parentNode->insertBefore($node, $loc->nextSibling);
} else {
$loc->parentNode->appendChild($node);
}
}
$doc->formatOutput = true;
$doc->save('output.xml');

Related

Returning count for an odata query

If I have a query such as:
http://myCRMOrg/api/data/v8.1/accounts?$filter=_chr_accountstatusid_value%20eq%2079A024B5-3D7C-E211-8B29-00155DC86B6F%20and%20accountid%20eq%20e929baaf-483b-e711-9425-00155dc0d345&$count=true
Please notice that I am specifying $count=true
It will return:
{
"#odata.context":"http://myCRMORG/api/data/v8.1/$metadata#accounts","#odata.count":1,"value":[
{
"#odata.etag":"W/\"1812635\"","
//100 fields and lots of data
}
]
}
How can we reconstruct this query to simply return 1?
I'm not sure if I'm understanding your question properly because if you filter Accounts by AccountId, you'll only ever get 0 or 1 results. So, if you get a result, you know the count is 1.
Anyway, to get a count, you can use a proper FetchXml aggregate like so:
https://xedev29.api.crm.dynamics.com/api/data/v8.2/accounts?fetchXml=
<fetch aggregate='true'>
<entity name='account'>
<attribute name='accountid' aggregate='count' alias='Count' />
</entity>
</fetch>
Which returns:
{
"#odata.context":"https://xedev29.api.crm.dynamics.com/api/data/v8.2/$metadata#accounts","value":[
{
"Count":337
}
]
}
And feel free to add your filters to the FetchXml:
https://xedev29.api.crm.dynamics.com/api/data/v8.2/accounts?fetchXml=
<fetch aggregate='true'>
<entity name='account'>
<attribute name='accountid' aggregate='count' alias='Count' />
<filter type='and' >
<condition attribute='chr_accountstatusid' operator='eq' value='D1C4CD52-1E51-E711-8122-6C3BE5B3B698'/>
<condition attribute='statecode' operator='eq' value='0' />
</filter>
</entity>
</fetch>
Of course you are subject to the usual FetchXml aggregate limitations (i.e. count tops out at 50K rows). Though I have discovered ways around this if you need it.
I also should have mentioned that there's no need to return all the fields, so we can use &$select=accountid.
You can get the #odata.count with an associative reference: result["#odata.count"]
Here's a full example:
function count(){
var req = new XMLHttpRequest();
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts?$select=accountid&$filter=accountid%20eq%20D1C4CD52-1E51-E711-8122-6C3BE5B3B698&$count=true", true);
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("Prefer", "odata.include-annotations=\"*\"");
req.onreadystatechange = function() {
if (this.readyState === 4) {
req.onreadystatechange = null;
if (this.status === 200) {
var result = JSON.parse(this.response);
console.log(result["#odata.count"]);
} else {
Xrm.Utility.alertDialog(this.statusText);
}
}
};
req.send();
}
Furthermore, I should mention that if you're doing significant work with the WebAPI, Jason Lattimer's CRMRESTBuilder is very handy.
And you might also want to check out David Yack's WebAPI helper.
I had same issue. What I did is I added count before filter and it worked. Example:
req.open("GET", Xrm.Page.context.getClientUrl() + "/api/data/v8.2/accounts/$count/?$select=accountid&$filter=accountid%20eq%20D1C4CD52-1E51-E711-8122-6C3BE5B3B698&", true);

Phalcon PHP post link with JavaScript confirmation dialog

I am developing a CRUD system in Phalcon PHP (version 1.3.4).
My goal is to create a link (delete row), that asks for confirmation on click (JavaScript confirmation box) and then goes (request type POST) to the link.
So lets say a user clicks on the "delete row" button.
JavaScript confirmation "Are you sure you want to delete this row?"
User clicks "yes"
Webpage does a POST to "/users/delete/1"
I know CakePHP has a function (FormHelper::postLink()) that does exactly that.
I was wondering if Phalcon PHP also had a function like this.
I see three possibilities to achieve what you want. One is to create a macro in Volt template, second is to add a function to your View. Third and closest to - what I understand is your wish - is to extend Phalcons tag helper and this is part I will describe here.
Phalcon has its own Tag helper to allow you to easily create some elements. postLink is not a part that is implemented there, but you can easily achieve it. In my example I have namespace of Application with class of Tag that extends from \Phalcon\Tag. This is my base for this tutorial.
// Tag.php
namespace Application;
class Tag extends \Phalcon\Tag
{
static public function postLink() {
return '<strong>TEST TAG</strong>';
}
}
To force Phalcon DI to use this class, it is necessary to override it's standard declaration from engine by declaring it by hand as a new DI service:
// services.php
$di['tag'] = function() {
return new \Application\Tag();
};
You can test if it is working properly by typing {{ tag.postLink() }} in Volt template or with $this->tag->postLink() if using phtml template.
Now you can fill your Tag::postLink() method with HTML and parameters you wish it will produce:
namespace Application;
class Tag extends \Phalcon\Tag
{
static $forms = [];
static public function postLink($title, $url, $options = array()) {
// random & unique form ID
while ($randId = 'f_' . mt_rand(9000, 999999)) {
if (!isset(self::$forms[$randId])) {
self::$forms[$randId] = true;
break;
}
}
// dialog message
$dialogMessage = isset($options['message']) && $options['message'] ? $options['message'] : 'Are you sure you want to go on?';
$html = <<<HTML
<form action="{$url}" method="post" id="{$randId}">
<!-- maybe not necessary part -->
<input type="hidden" name="confirmed" value="1" />
</form>
{$title}
HTML;
return $html;
}
}
Now you can run it like this:
{{ tag.postLink('delete', '/users/delete/1') }}
{% set formOptions = ['message' : 'Are you sure you want to delete user Kialia Kuliambro?'] %}
{{ tag.postLink('delete', '/users/delete/1', formOptions) }}
{{ tag.postLink('delete', '/users/delete/1', ['message' : 'Are you sure you want to delete user Kialia Kuliambro?']) }}
Have fun extending :)
There's a few ways to implement such behavior in phalcon. Before anything, we need to understand how views and view helpers work in phalcon. And if you pay close attention, you'll notice, both .volt and .phtml have direct access to the DI.
In volt, for example, you can access the flash service, and output its messages by calling:
{{ flash.output() }}
which gets converted to the phtml: <?php echo $this->flash->output(); ?>
Thus my solution focuses on defining a new service in the DI which volt can access. In CakePHP, the syntax for postLink(), looks something like: echo $this->Form->postLink() while the function is actually defined in a class named FormHelper. So my solution will do the same thing, define a class FormHelper, then inject it into the view under the name Form.
Create an app/helpers/ directory.
Update your app/config/config.php file adding a reference to our new directory: 'helpersDir'=> APP_PATH . '/app/helpers/'
Update your app/config/loader.php file adding $config->application->helpersDir to the registered directories.
Create a new file app/helpers/FormHelper.php
Copy-paste the following code into the file:
<?php
use Phalcon\Tag;
class FormHelper extends Tag
{
protected $_lastAction = '';
public function dottedNameToBracketNotation($name)
{
$parts=explode('.',$name);
$first = array_shift($parts);
$name=$first . ($parts ? '[' . implode('][', $parts) . ']' : '');
return $name;
}
protected function flatten(array $data, $separator = '.')
{
$result = [];
$stack = [];
$path = null;
reset($data);
while (!empty($data)) {
$key = key($data);
$element = $data[$key];
unset($data[$key]);
if (is_array($element) && !empty($element)) {
if (!empty($data)) {
$stack[] = [$data, $path];
}
$data = $element;
reset($data);
$path .= $key . $separator;
} else {
$result[$path . $key] = $element;
}
if (empty($data) && !empty($stack)) {
list($data, $path) = array_pop($stack);
reset($data);
}
}
return $result;
}
protected function _confirm($message, $okCode, $cancelCode = '', $options = [])
{
$message = json_encode($message);
$confirm = "if (confirm({$message})) { {$okCode} } {$cancelCode}";
if (isset($options['escape']) && $options['escape'] === false) {
$confirm = $this->h($confirm);
}
return $confirm;
}
public function h($text, $double = true, $charset = 'UTF-8')
{
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, $charset, $double);
}
protected function _lastAction($url)
{
$action = $url;//Router::url($url, true);
$query = parse_url($action, PHP_URL_QUERY);
$query = $query ? '?' . $query : '';
$this->_lastAction = parse_url($action, PHP_URL_PATH) . $query;
}
public function postLink($title, $url = null, array $options = [])
{
$out='';
$options += ['block' => null, 'confirm' => null];
$requestMethod = 'POST';
if (!empty($options['method'])) {
$requestMethod = strtoupper($options['method']);
unset($options['method']);
}
$confirmMessage = $options['confirm'];
unset($options['confirm']);
$formName = str_replace('.', '', uniqid('post_', true));
$formOptions = [
'name' => $formName,
'style' => 'display:none;',
'method' => 'post',
];
if (isset($options['target'])) {
$formOptions['target'] = $options['target'];
unset($options['target']);
}
$formOptions[0]=$url;
$out.=$this->form($formOptions);
$out .= $this->hiddenField(['_method','value' => $requestMethod]);
$fields = [];
if (isset($options['data']) && is_array($options['data'])) {
foreach ($this->flatten($options['data']) as $key => $value) {
$out .= $this->hiddenField([$this->dottedNameToBracketNotation($key),'value' => $value]);
}
unset($options['data']);
}
$out .= $this->endForm();
//This is currently unsupported
if ($options['block']) {
if ($options['block'] === true) {
$options['block'] = __FUNCTION__;
}
//$this->_View->append($options['block'], $out);
$out = '';
}
unset($options['block']);
$url = '#';
$onClick = 'document.' . $formName . '.submit();';
if ($confirmMessage) {
$options['onclick'] = $this->_confirm($confirmMessage, $onClick, '', $options);
} else {
$options['onclick'] = $onClick . ' ';
}
$options['onclick'] .= 'event.returnValue = false; return false;';
$options[0]=$url;
$options[1]=$title;
$options[2]=false;
$out .= $this->linkTo($options);
return $out;
}
}
Edit your app/config/services.php file and add in:
$di->set('Form',function () {
return new FormHelper();
});
(you could make "Form" lowercase if you want, both work. I made it capital to closer resemble CakePHP's syntax. Do note that Volt is case sensitive when trying to access services but phtml will lowercase it.)
Edit the template you want to test the code on, such as app/views/index/test.volt
Copy-paste the following code into there:
{{ Form.postLink(' Delete','',['confirm':'Are you sure you want to delete #4?','data':['a':['b','c']]]) }}
Alternatively for phtml, use: <?php echo $this->form->postLink(' Delete', '', array('confirm' => 'Are you sure you want to delete #4?', 'data' => array('a' => array('b', 'c')))); ?>
Run it, and watch it work its magic, just render your index/test.volt template by visiting /index/test in your address bar. (Make sure you defined such an action in your index controller)
In terms, of other solutions, you could also use $compiler->addFunction() to make functions available to volt, one at time. The page in the manual gives the example of $compiler->addFunction('shuffle', 'str_shuffle');. You can attempt to override the factoryDefault for "tag" in the DI, and use the helper we already defined which extends tag. So you'd just change it from "form" to "tag" like so: $di->set('tag',function () {return new FormHelper();}); but, as you can see, it won't make the function postLink() available to volt as a function, you'll notice you still need to access it as tag.postLink(). Rather, all the \Phalcon\Tag functions are actually hard-coded into the volt engine. You can see this clearly by viewing the zephir source code of the \Phalcon\Mvc\View\Engine\Volt\Compiler class available over here. For your convenience, and in case the link ever gets broken, I have posted a snippet here which shows the "tag" functions in volt are actually hard-coded into it:
if method_exists(className, method) {
let arrayHelpers = this->_arrayHelpers;
if typeof arrayHelpers != "array" {
let arrayHelpers = [
"link_to": true,
"image": true,
"form": true,
"select": true,
"select_static": true,
"submit_button": true,
"radio_field": true,
"check_field": true,
"file_field": true,
"hidden_field": true,
"password_field": true,
"text_area": true,
"text_field": true,
"email_field": true,
"date_field": true,
"tel_field": true,
"numeric_field": true,
"image_input": true
];
let this->_arrayHelpers = arrayHelpers;
}
if isset arrayHelpers[name] {
return "$this->tag->" . method . "(array(" . arguments . "))";
}
return "$this->tag->" . method . "(" . arguments . ")";
}
So, if you'd like to "hack" in a few more methods by extending the \Phalcon\Tags class, you're out of luck. However, as demonstrated on the volt documentation page, there exists the concept of registering custom extensions to work with volt. The documentation gives the example of: $compiler->addExtension(new PhpFunctionExtension());
Where the source of the class is:
<?php
class PhpFunctionExtension
{
/**
* This method is called on any attempt to compile a function call
*/
public function compileFunction($name, $arguments)
{
if (function_exists($name)) {
return $name . '('. $arguments . ')';
}
}
}
This would allow volt access to any function you'd like, without having to manually register every possible function you could possibly ever need. You can test this by trying to access str_shuffle in volt, like we did before with $compiler->addFunction('shuffle', 'str_shuffle'); but this time without having to register it.
In terms of other solutions, you could also try to integrate CakePHP and PhalconPHP together, and attempt to call CakePHP's view helpers from PhalconPHP, but then you'd run into a problem of CakePHP not understanding your router setup you have configured in Phalcon. But, if you're determined, you could code all the routes and config for CakePHP and run it alongside PhalconPHP, but I'd highly discourage such a desperate workaround. And, finally, if you understand how the function works, and you barely use it, you could get away with just hard-coding the HTML in the first place. Honestly, CakePHP's logic doesn't look so sound to me in the first place because it has to corrupt your HTML document with a form inserted which can bother your layout. I think it would make more sense to generate a form dynamically with JavaScript, if we're using JavaScript already, and append it to the <body> when the button is clicked, then submit the form we just created dynamically. But, you wanted a CakePHP implementation, so I coded it as close to the logic they used as possible. It's not perfect, in terms of supporting all their features, such as block, but it should suit most of your needs.
I can always revise my implementation, but I think it demonstrates how to work with Phalcon pretty well for those migrating from CakePHP.

Programmatically hide simple pref

I can't seem to figure out how to programmatically hide or show a setting.
I have tried this:
function onSwitchChange(prefName) {
var ms = require("sdk/simple-prefs").prefs.option1;
if(ms == "S"){
require("sdk/simple-prefs").prefs.option2.hidden = false;
}else{
require("sdk/simple-prefs").prefs.option2.hidden = true;
}
}
require("sdk/simple-prefs").on("option1", onSwitchChange);
you need to give your pref an oninputchanged attribute.
see here: MDN :: Inline Options - Setting element changed notifications
it looks like you're using firefox-addon-sdk so after you make your addon to xpi. rename the xpi to zip then extract it. then edit options.xul then re-zip the files, then re-rename it to .xpi.
the edit you need to make to options.xul is find the setting element of option2. then add to it this:
<setting title="option1" type="string" pref="blahBlahBlah" oninputchanged="if (this.value == 'S') { document.querySelector('setting[title=\"option1\"]').style.display='none'; } else { document.querySelector('setting[title=\"option1\"]').style.display=''; } ">
option2
</setting>

Programmatically invoke Html File plus Css and Javascript With ShowCase

I am unpacking a Zip File and load the index.html like that
MyWebViewControl.NavigateToLocalStreamUri(MyUrl, new MyStreamUriResolver());
But it only shows Plain Html. The
<link href="css/custom.css" rel="stylesheet">
for example doesn't get invoked. I don't have any idea why it doesn't work.
I don't get it. Why can i load a WebPage like stackoverflow with css and javascript, but when i try to load my own Html File it doesn't work.
Any suggestions how i can fix the problem?
EDIT:
ShowCase for my Problem
Read.me First!
JQuery link is not necessary. You can try it with only a css link too.
This is how you get the whole content:
private async Task<IInputStream> GetContent(string path)
{
try
{
var arr = path.Split('/');
var localFolder = KnownFolders.MusicLibrary;
var folder = await localFolder.GetFolderAsync("myhtmlunzip");
var file = await folder.GetFileAsync(arr[arr.Length-1]);
IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read).AsTask().ConfigureAwait(false);
if (true)
{
Windows.Storage.Streams.DataReader reader = new DataReader(stream);
await reader.LoadAsync((uint)stream.Size);
var fileContent = reader.ReadString((uint)stream.Size);
stream.Seek(0);
}
return stream;
}
catch
{
throw new Exception("Path is invalid");
}
}
Informations (MSDN LINK)

Get current url and create share link (yahoo messenger)

I have this function to get the current page url:
<?php
function currentPageURL() {
$curpageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {$curpageURL.= "s";}
$curpageURL.= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$curpageURL.= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
$curpageURL.= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
return $curpageURL;
}
echo currentPageURL();
?>
And I need to create a link to share the page's URL by a href.
I tried:
Link
But I'm not getting the currentPageURL; it's blank.
Just stumbled on this one. Seems like you're using a variable and not the function call in your href. This should work:
Link

Resources