Is there an easy way to add/remove/modify query parameters of a URL in Tritium? - moovweb

I saw a very manual way of doing this in another post: How do I add a query parameter to a URL?
This doesn't seem very intuitive, but someone there mentioned an easier way to accomplish this using the upcoming "URL scope". Is this feature out yet, and how would I use it?

If you're using the stdlib mixer, you should be able to use the URL scope which provides helper functions for adding, viewing, editing, and removing URL params. Here's a quick example:
$original_url = "http://cuteoverload.com/2013/08/01/buttless-monkey-jams?hi=there"
$new_url = url($original_url) {
log(param("hi"))
param("hello", "world")
remove_param("hi")
}
log($new_url)
Tritium Tester example here: http://tester.tritium.io/9fcda48fa81b6e0b8700ccdda9f85612a5d7442f
Almost forgot, link to docs: http://tritium.io/current (You'll want to click on the URL category).

AFAIK, there's no built-in way of doing so.
I'll post here how I did to append a query param, making sure that it does not get duplicated if already on the url:
Inside your functions/main.ts file, you can declare:
# Adds a query parameter to the URL string in scope.
# The parameter is added as the last parameter in
# the query string.
#
# Sample use:
# $("//a[#id='my_link]") {
# attribute("href") {
# value() {
# appendQueryParameter('MVWomen', '1')
# }
# }
# }
#
# That will add MVwomen=1 to the end of the query string,
# but before any hash arguments.
# It also takes care of deciding if a ? or a #
# should be used.
#func Text.appendQueryParameter(Text %param_name, Text %param_value) {
# this beautiful regex is divided in three parts:
# 1. Get anything until a ? or # is found (or we reach the end)
# 2. Get anything until a # is found (or we reach the end - can be empty)
# 3. Get the remainder (can be empty)
replace(/^([^#\?]*)(\?[^#]*)?(#.*)?$/) {
var('query_symbol', '?')
match(%2, /^\?/) {
$query_symbol = '&'
}
# first, it checks if the %param_name with this %param_value already exists
# if so, we don't do anything
match_not(%2, concat(%param_name, '=', %param_value)) {
# We concatenate the URL until ? or # (%1),
# then the query string (%2), which can be empty or not,
# then the query symbol (either ? or &),
# then the name of the parameter we are appending,
# then an equals sign,
# then the value of the parameter we are appending
# and finally the hash fragment, which can be empty or not
set(concat(%1, %2, $query_symbol, %param_name, '=', %param_value, %3))
}
}
}
The other features you want (remove, modify) can be achieved similarly (by creating a function inside functions/main.ts and leveraging some regex magic).
Hope it helps.

Related

evaluate condition assigned to a variable

i am using module Excel::Writer::XLSX and i need to evaluate this condition to check if the sheet was created or not (i need to only execute certain actions if the sheet already exists)
my $sheet = $workbook->add_worksheet($filters{$filter}{description});
how can i do that please ?
knowing that if the sheet already exists, the add_worksheet method "dies" with an error like :
Worksheet name 'All Users', with case ignored, is already used. at ./xxxx.pl line 203.
naturlly, doing something like this doesn't work as i believe it evaluates the variable assignment :
if (my $sheet = $workbook->add_worksheet($filters{$filter}{description});) {
# good, sheet doesn't already exists and was created
# i can place my code here to insert header rows etc./ colors
} else {
# program fires a message like :
# Worksheet name 'XXXXXX', with case ignored, is already used. at XXX
# no need to place code for column headers etc., sheet already exists
}
You could use
my $name = $filters{$filter}{description};
my $sheet =
$workbook->get_worksheet_by_name( $name ) ||
$workbook->add_worksheet( $name );
nvm, i used a hash and i'm checking the hash
if (!$sheets{$filter}) {
$sheets{$filter} = $workbook->add_worksheet($filters{$filter}{description});
works nicely

What are all the Unicode properties a Perl 6 character will match?

The .uniprop returns a single property:
put join ', ', 'A'.uniprop;
I get back one property (the general category):
Lu
Looking around I didn't see a way to get all the other properties (including derived ones such as ID_Start and so on). What am I missing? I know I can go look at the data files, but I'd rather have a single method that returns a list.
I am mostly interested in this because regexes understand properties and match the right properties. I'd like to take any character and show which properties it will match.
"A".uniprop("Alphabetic") will get the Alphabetic property. Are you asking for what other properties are possible?
All these that have a checkmark by them will likely work. This just displays that status of roast testing for it https://github.com/perl6/roast/issues/195
This may more more useful for you, https://github.com/rakudo/rakudo/blob/master/src/core/Cool.pm6#L396-L483
The first hash is just mapping aliases for the property names to the full names. The second hash specifices whether the property is B for boolean, S for a string, I for integer, nv for numeric value, na for Unicode Name and a few other specials.
If I didn't understand you question please let me know and I will revise this answer.
Update: Seems you want to find out all the properties that will match. What you will want to do is iterate all of https://github.com/rakudo/rakudo/blob/master/src/core/Cool.pm6#L396-L483 and looking only at string, integer and boolean properties. Here is the full thing: https://gist.github.com/samcv/ae09060a781bb4c36ae6cac80ea9325f
sub MAIN {
use Test;
my $char = 'a';
my #result = what-matches($char);
for #result {
ok EVAL("'$char' ~~ /$_/"), "$char ~~ /$_/";
}
}
use nqp;
sub what-matches (Str:D $chr) {
my #result;
my %prefs = prefs();
for %prefs.keys -> $key {
given %prefs{$key} {
when 'S' {
my $propval = $chr.uniprop($key);
if $key eq 'Block' {
#result.push: "<:In" ~ $propval.trans(' ' => '') ~ ">";
}
elsif $propval {
#result.push: "<:" ~ $key ~ "<" ~ $chr.uniprop($key) ~ ">>";
}
}
when 'I' {
#result.push: "<:" ~ $key ~ "<" ~ $chr.uniprop($key) ~ ">>";
}
when 'B' {
#result.push: ($chr.uniprop($key) ?? "<:$key>" !! "<:!$key>");
}
}
}
#result;
}
sub prefs {
my %prefs = nqp::hash(
'Other_Grapheme_Extend','B','Titlecase_Mapping','tc','Dash','B',
'Emoji_Modifier_Base','B','Emoji_Modifier','B','Pattern_Syntax','B',
'IDS_Trinary_Operator','B','ID_Continue','B','Diacritic','B','Cased','B',
'Hangul_Syllable_Type','S','Quotation_Mark','B','Radical','B',
'NFD_Quick_Check','S','Joining_Type','S','Case_Folding','S','Script','S',
'Soft_Dotted','B','Changes_When_Casemapped','B','Simple_Case_Folding','S',
'ISO_Comment','S','Lowercase','B','Join_Control','B','Bidi_Class','S',
'Joining_Group','S','Decomposition_Mapping','S','Lowercase_Mapping','lc',
'NFKC_Casefold','S','Simple_Lowercase_Mapping','S',
'Indic_Syllabic_Category','S','Expands_On_NFC','B','Expands_On_NFD','B',
'Uppercase','B','White_Space','B','Sentence_Terminal','B',
'NFKD_Quick_Check','S','Changes_When_Titlecased','B','Math','B',
'Uppercase_Mapping','uc','NFKC_Quick_Check','S','Sentence_Break','S',
'Simple_Titlecase_Mapping','S','Alphabetic','B','Composition_Exclusion','B',
'Noncharacter_Code_Point','B','Other_Alphabetic','B','XID_Continue','B',
'Age','S','Other_ID_Start','B','Unified_Ideograph','B','FC_NFKC_Closure','S',
'Case_Ignorable','B','Hyphen','B','Numeric_Value','nv',
'Changes_When_NFKC_Casefolded','B','Expands_On_NFKD','B',
'Indic_Positional_Category','S','Decomposition_Type','S','Bidi_Mirrored','B',
'Changes_When_Uppercased','B','ID_Start','B','Grapheme_Extend','B',
'XID_Start','B','Expands_On_NFKC','B','Other_Uppercase','B','Other_Math','B',
'Grapheme_Link','B','Bidi_Control','B','Default_Ignorable_Code_Point','B',
'Changes_When_Casefolded','B','Word_Break','S','NFC_Quick_Check','S',
'Other_Default_Ignorable_Code_Point','B','Logical_Order_Exception','B',
'Prepended_Concatenation_Mark','B','Other_Lowercase','B',
'Other_ID_Continue','B','Variation_Selector','B','Extender','B',
'Full_Composition_Exclusion','B','IDS_Binary_Operator','B','Numeric_Type','S',
'kCompatibilityVariant','S','Simple_Uppercase_Mapping','S',
'Terminal_Punctuation','B','Line_Break','S','East_Asian_Width','S',
'ASCII_Hex_Digit','B','Pattern_White_Space','B','Hex_Digit','B',
'Bidi_Paired_Bracket_Type','S','General_Category','S',
'Grapheme_Cluster_Break','S','Grapheme_Base','B','Name','na','Ideographic','B',
'Block','S','Emoji_Presentation','B','Emoji','B','Deprecated','B',
'Changes_When_Lowercased','B','Bidi_Mirroring_Glyph','bmg',
'Canonical_Combining_Class','S',
);
}
OK, so here's another take on answering this question, but the solution is not perfect. Bring the downvotes!
If you join #perl6 channel on freenode, there's a bot called unicodable6 which has functionality that you may find useful. You can ask it to do this (e.g. for character A and π simultaneously):
<AlexDaniel> propdump: Aπ
<unicodable6> AlexDaniel, https://gist.github.com/b48e6062f3b0d5721a5988f067259727
Not only it shows the value of each property, but if you give it more than one character it will also highlight the differences!
Yes, it seems like you're looking for a way to do that within perl 6, and this answer is not it. But in the meantime it's very useful. Internally Unicodable just iterates through this list of properties. So basically this is identical to the other answer in this thread.
I think someone can make a module out of this (hint-hint), and then the answer to your question will be “just use module Unicode::Propdump”.

Powershell: Turn period delimited string into object properties

I have a string that looks something like this:
$string = "property1.property2.property3"
And I have an object, we'll call $object. If I try to do $object.$string it doesn't interpret it that I want property3 of property2 of property1 of $object, it thinks I want $object."property1.property2.property3".
Obviously, using split('.') is where I need to be looking, but I don't know how to do it if I have an unknown amount of properties. I can't statically do:
$split = $string.split('.')
$object.$split[0].$split[1].$split[2]
That doesn't work because I don't know how many properties are going to be in the string. So how do I stitch it together off of n amounts of properties in the string?
A simple cheater way to do this would be to use Invoke-Expression. It will build the string and execute it in the same way as if you typed it yourself.
$string = "property1.property2.property3"
Invoke-Expression "`$object.$string"
You need to escape the first $ since we don't want that expanded at the same time as $string. Typical warning: Beware of malicious code execution when using Invoke-Expression since it can do anything you want it to.
In order to avoid this you would have to build a recursive function that would take the current position in the object and pass it the next breadcrumb.
Function Get-NestedObject{
param(
# The object we are going to return a propery from
$object,
# The property we are going to return
$property,
# The root object we are starting from.
$rootObject
)
# If the object passed is null then it means we are on the first pass so
# return the $property of the $rootObject.
if($object){
return $object.$property
} else {
return $rootObject.$property
}
}
# The property breadcrumbs
$string = '"Directory Mappings"."SSRS Reports"'
# sp
$delimetedString = $String.Split(".")
$nestedObject = $null
Foreach($breadCrumb in $delimetedString){
$nestedObject = Get-NestedObject $nestedObject $breadcrumb $settings
}
$nestedObject
There are some obvious places where that function could be hardened and documented better but that should give you an idea of what you could do.
What's the use case here? You can split the string as you've described. This will create an array, and you can count the number of elements in the array so that n is known.
$string = "property1.property2.property3"
$split = $string.split('.')
foreach($i in 0..($split.Count -1)){
Write-Host "Element $i is equal to $($split[$i])"
$myString += $split[$i]
}

Typoscript: how do I add a parameter to all links in the RTE?

I want to add a parameter to all links entered in the RTE by the user.
My initial idea was to do this:
lib.parseFunc_RTE.tags.link {
typolink.parameter.append = TEXT
typolink.parameter.append.value = ?flavor=lemon
}
So for example:
http://domain.com/mypage.php
becomes
http://domain.com/mypage.php?flavor=lemon
which sounds great -- as long as the link does not already have a query string!
In that case, I obviously end up with two question marks in the URL
So for example:
http://domain.com/prefs.php?id=1234&unit=moon&qty=300
becomes
http://domain.com/prefs.php?id=1234&unit=moon&qty=300?flavor=lemon
Is there any way to add my parameter with the correct syntax, depending on whether the URL already has a query string or not? Thanks!
That would be the solution:
lib.parseFunc_RTE.tags.link {
typolink.additionalParams = &flavor=lemon
}
Note that it has to start with an &, typo3 then generates a valid link. The parameter in the link also will be parsed with realURL if configured accordingly.
Edit: The above solution only works for internal links as described in the documentation https://docs.typo3.org/typo3cms/TyposcriptReference/Functions/Typolink/Index.html
The only solution that works for all links that I see is to use a userFunc
lib.parseFunc_RTE.tags.link {
typolink.userFunc = user_addAdditionalParams
}
Then you need to create a php script and include in your TS with:
includeLibs.rteScript = path/to/yourScript.php
Keep in mind that includeLibs is outdated, so if you are using TYPO3 8.x (and probably 7.3+) you will need to create a custom extension with just a few files
<?php
function user_addAdditionalParams($finalTagParts) {
// modify the url in $finalTagParts['url']
// $finalTagParts['TYPE'] is an indication of link-kind: mailto, url, file, page, you can use it to check if you need to append the new params
switch ($finalTagParts['TYPE']) {
case 'url':
case 'file':
$parts = explode('#', $finalTagParts['url']);
$finalTagParts['url'] = $parts[0]
. (strpos($parts[0], '?') === false ? '?' : '&')
. 'newParam=test&newParam=test2'
. ($parts[1] ? '#' . $parts[1] : '');
break;
}
return '<a href="' . $finalTagParts['url'] . '"' .
$finalTagParts['targetParams'] .
$finalTagParts['aTagParams'] . '>'
}
PS: i have not tested the actual php code, so it can have some errors. If you have troubles, try debugging the $finalTagParts variable
Test whether the "?" character is already in the URL and append either "?" or "&", then append your key-value pair. There's a CASE object available in the TypoScript Reference, with an example you can modify for your purpose.
For anyone interested, here's a solution that worked for me using the replacement function of Typoscript. Hope this helps.
lib.parseFunc_RTE.tags.link {
# Start by "replacing" the whole URL by itself + our string
# For example: http://domain.com/?id=100 becomes http://domain.com/?id=100?flavor=lemon
# For example: http://domain.com/index.html becomes http://domain.com/index.html?flavor=lemon
typolink.parameter.stdWrap.replacement.10 {
#this matches the whole URL
search = #^(.*)$#i
# this replaces it with itself (${1}) + our string
replace =${1}?flavor=lemon
# in this case we want to use regular expressions
useRegExp = 1
}
# After the first replacement is done, we simply replace
# the first '?' by '?' and all others by '&'
# the use of Option Split allow this
typolink.parameter.stdWrap.replacement.20 {
search = ?
replace = ? || & || &
useOptionSplitReplace = 1
}
}

How should I redirect users in a formmail script?

So I'm using a basic formmail script. Within the script I'm using a redirect variable. The value of the redirect is something like:
http://www.mysite.com/NewOLS_GCUK_EN/bling.aspx?BC=GCUK&IBC=CSEE&SIBC=CSEE
When the redirect action happens however, the URL appears in the browser as:
http://www.mysite.com/NewOLS_GCUK_EN/bling.aspx?BC=GCUK&IBC=CSEE&SIBC=CSEE
You can see the & characters are replaced with &
Is there any way to fix this?
Maybe you can edit the script with a string substitution:
$myRedirectURL =~ s/\&/\&/g;
Or perhaps look in the script where the opposite substitution is taking place, and comment out that step.
HTML::Entities's decode_entities could decode this for you:
$redirect_target = decode_entities($redirect_target);
But passing the destination URL as HTTP argument (e.g. hidden form field) is dangerous (as #Sinan Ünür already said in the comments). Better store the target URL within your script and pass a selector from the form:
if ($selector eq 'home') { $target_url = 'http://www.foo.bar/'; }
elsif ($selector eq 'bling') { $target_url = 'http://www.foo.bar/NewOLS_GCUK_EN/bling.aspx'; }
else {
$target_url = 'http://www.foo.bar/default.html'; # Fallback/default value
}
Using a Hash would be shorter:
my %targets = {
home => 'http://www.foo.bar/',
bling => '/NewOLS_GCUK_EN/bling.aspx',
};
$target_url = $targets{$selector} || '/default_feedback_thanks.html';