XMLHttpRequest - append php function to .json?add_fields ajax request - javascript

I am trying to update someone else's code, which uses a XMLHttpRequest setup to get product information from the server for use on some SilverStripe templates. I want to grab the url() function from Product.php so I can use it to get the url for the Product data object and send it to Google Analytics. However, simply appending it to the existing add_fields data does not work--the url function does not get retrieved.
I'm not very familiar with XMLHttpRequests so I'm kind of clueless as to what to do here.
Here is the JavaScript code that is getting the product data:
document.addEventListener("DOMContentLoaded", function(event) {
var productCatalogService = (function() {
var endpoint = "/api/v1/Product/";
return {
'getProductById': function(id, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', endpoint + id + ".json?add_fields=NutritionalInformationLabelURL,SortOrder,BeautyShotURL,url,Recipe"); //url function is not grabbed
xhr.onload = function() {
if (xhr.status === 200) {
callback && callback(JSON.parse(xhr.responseText));
}
else {
console.error('Request failed. Returned status of ' + xhr.status);
}
};
xhr.send();
}
};
})();
var utils = (function() {
return {
'removeClass': function(node, className) {
node.className = node.className.replace(className, '');
return node;
},
'addClass': function(node, className) {
node.className = node.className.replace(className, '');
node.className += " " + className;
},
'hasClass': function(node, className) {
return node.className.indexOf(className) >= 0;
}
}
})();
var changeProduct = function(product) {
var name = document.querySelector('.product-name'),
subname = document.querySelector('.product-subname'),
tagline = document.querySelector('.product-tagline'),
description = document.querySelector('.product-description'),
beautyShot = document.querySelector('.beauty-shot'),
nutritionFacts = document.querySelector('.ingredients-list'),
mobileNutritionLabel = document.querySelector('.mobile-nutrition-label img'),
nutritionLabel = document.querySelector('.nutritional-label img'),
recipeName = document.querySelector('.recipe-name'),
recipeDescription = document.querySelector('.recipe-description'),
recipeContainer = document.querySelector('.recipe-container');
name.innerHTML = product.Name;
subname.innerHTML = product.SubName;
description.innerHTML = product.Description;
tagline.innerHTML = product.Tagline;
beautyShot.src = product.BeautyShotURL;
if(product.NutritionalInformationLabelURL){
nutritionLabel.src = product.NutritionalInformationLabelURL;
mobileNutritionLabel.src = product.NutritionalInformationLabelURL;
}
if(product.NutritionFacts){
nutritionFacts.innerHTML = product.NutritionFacts;
if(utils.hasClass(nutritionFacts, 'hidden')) {
utils.removeClass(nutritionFacts, 'hidden');
}
} else {
utils.addClass(nutritionFacts, 'hidden');
}
// var pagePath = product.url();
console.log(product.url); //returns undefined
typeof(ga) !== "undefined" && ga('send', 'pageview', {
'page': location.pathname, //want to use the url() function in Product.php here
'title': product.PageTitle
});
};
NodeList.prototype.forEach = Array.prototype.forEach;
var products = document.querySelectorAll('.carousel-products .product');
products.forEach(function(product) {
product.onclick = function() {
var productId = product.getAttribute('data-product-id');
productCatalogService.getProductById(productId, function(product) {
console.log(product);
changeProduct(product); //add recipe data to be pulled in here (fields are above)
});
};
});
});
Product.php
<?php
class Product extends DataObject implements Pageable, Searchable {
private static $api_access = true;
private static $db = [
'Name' => 'varchar(255)',
'SubName' => 'varchar(255)',
'Tagline' => 'varchar(255)',
'Description' => 'HTMLText',
'WhereToBuy' => 'varchar(500)', // external link
'NutritionFacts' => 'HTMLText',
'PageTitle' => 'varchar(250)',
'MetaKeywords' => 'Text',
'MetaDescription' => 'Text',
'SortOrder' =>'Int'
];
private static $has_one = [
'BeautyShot' => 'Image',
'ThumbImage' => 'Image',
'NutritionalInformationLabel' => 'Image',
'Category' => 'Category',
];
private static $summary_fields = [
'GridThumbnail' => 'Photo',
'Name' => 'Name'
];
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->addFieldToTab('Root.Main', new TextField("Name", "Name"));
$fields->addFieldToTab('Root.Main', new TextField("SubName", "SubName"));
$fields->addFieldToTab('Root.Main', new TextField("Tagline", "Tagline"));
$fields->addFieldToTab("Root.Main", new HtmlEditorField("Description", "Description"));
$fields->addFieldToTab('Root.Main', new TextField("WhereToBuy", "WhereToBuy"));
$fields->addFieldToTab("Root.Main", new HtmlEditorField("NutritionFacts", "NutritionFacts"));
$fields->addFieldToTab("Root.Main", new UploadField("BeautyShot", "BeautyShot"));
$fields->addFieldToTab("Root.Main", new UploadField("ThumbImage", "ThumbImage"));
$fields->addFieldToTab("Root.Main", new UploadField("NutritionalInformationLabel", "NutritionalInformationLabel"));
$fields->addFieldToTab('Root.SEO', new TextField("PageTitle", "PageTitle"));
$fields->addFieldToTab('Root.SEO', new TextareaField("MetaKeywords", "MetaKeywords"));
$fields->addFieldToTab('Root.SEO', new TextareaField("MetaDescription", "MetaDescription"));
$fields->removeByName('SortOrder');
return $fields;
}
public function getGridThumbNail() {
if ($this->BeautyShot()->exists()) {
return $this->BeautyShot()->SetWidth(100);
}
return '(no image)';
}
public function getBeautyShotURL() {
return $this->BeautyShot()->URL;
}
public function getNutritionalInformationLabelURL() {
if ($this->NutritionalInformationLabel()->Exists()) {
return $this->NutritionalInformationLabel()->URL;
} else {
return "";
}
}
public function getCouponImageURL() {
if ($this->CouponImage()->Exists()) {
return $this->CouponImage()->URL;
} else {
return "";
}
}
public function getProductFullName(){
return $this->Name." ".$this->SubName;
}
public function AbsoluteLink() {
return Director::absoluteURL($this->url());
}
private function url() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
// lifted from Artisa
public function MetaTags() {
$tags = "";
$generator = trim(Config::inst()->get('SiteTree', 'meta_generator'));
if (!empty($generator)) {
$tags .= "<meta name=\"generator\" content=\"" . Convert::raw2att($generator) . "\" />\n";
}
$charset = Config::inst()->get('ContentNegotiator', 'encoding');
$tags .= "<meta http-equiv=\"Content-type\" content=\"text/html; charset=$charset\" />\n";
if($this->MetaDescription) {
$tags .= "<meta name=\"description\" content=\"" . Convert::raw2att($this->MetaDescription) . "\" />\n";
}
if($this->MetaKeywords) {
$tags .= "<meta name=\"keywords\" content=\"" . Convert::raw2att($this->MetaKeywords) . "\" />\n";
}
if(Permission::check('CMS_ACCESS_CMSMain')
&& in_array('CMSPreviewable', class_implements($this))
&& !$this instanceof ErrorPage
&& $this->ID > 0
) {
$tags .= "<meta name=\"x-page-id\" content=\"{$this->ID}\" />\n";
$tags .= "<meta name=\"x-cms-edit-link\" content=\"" . $this->CMSEditLink() . "\" />\n";
}
$this->extend('MetaTags', $tags);
return $tags;
}
public function canView($member = null){
return true;
}
public function canEdit($member = null) {
return true;
}
public function canCreate($member = null) {
return true;
}
public function slug()
{
return Utilities::friendlyName($this->Name);
}
public function Link()
{
return $this->url();
}
public function getTitleFields() {
return ['Name', 'SubName'];
}
public function getContentFields() {
return ['Description'];
}
public static function getSearchFilter() {
return [];
}
}
// Handles Products and categories
class ProductCsvBulkImporter extends CsvBulkLoader {
protected function processRecord($record, $columnMap, &$results, $preview = false) {
$categoryName = $record['Main Category'];
$productName = $record['Product ID'];
$productSubName = $record['Product Type'];
$productTagline = $record['Product Label'];
$productDescription = $record['Product Description'];
$productKeywords = $record['Keyphrase'];
$category = Category::get()
->filter(['Name' => $categoryName])
->first();
if (!$category) {
$category = new Category();
$category->Name = $categoryName;
$category->write();
}
$product = Product::get()
->filter(['Name' => $productName])
->first();
if (!$product) {
$product = new Product();
}
$product->PageTitle = sprintf("%s %s", $productName, $productSubName);
$product->Name = $productName;
$product->SubName = $productSubName;
$product->Tagline = $productTagline;
$product->Description = $productDescription;
$product->MetaKeywords = $productKeywords;
$product->CategoryID = $category->ID;
$product->write();
return $product->ID;
}
}
I don't know if the code, as it's setup now, is best practice or not as I didn't make it, so if there are mistakes, I can't tell for sure.
Is there some way to append the url() function from Product.php to the .json?add_fields ajax response?

As you can see in the Product class, the url() method it's private, so you don't have access to it outside that class:
private function url() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
If you change that to:
public function url() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
it'll probably work... That's all I can say based on the code you submitted. You should know, there's probably a reason why that url() method is private - most probably it's only used internally in the Product class.
If it's still not working, try to duplicate that function like this:
public function getUrl() {
return sprintf("/home/products/%s/%s", $this->Category()->slug(), $this->slug());
}
...and then in the JS code you can use it like this:
console.log(product.Url);
As you can see, you have calls like this in the JS code: product.BeautyShotURL, but the actual method in the Product class it's called getBeautyShotURL(), so it should work with product.Url (this might also work tough: product.getUrl)

Related

WordPress callback function is called twice

i have been developing a WordPress plugin that has a form that sends some data to a Database.
My problem is that every time i click the submit button the callback runs twice, and the information that appears in my database is duplicated.
My jQuery code is:
$("#submit_btn").click( function (event) {
event.preventDefault();
let uuid = uuidv4()
let form_serialize = $("form").serializeArray();
let dataForm = {
"id": uuid,
'submitId': uuid
}
$.each(form_serialize, function (i, field) {
dataForm[field.name] = field.value
});
$.ajax({
url: ccandidates.ajax_url,
type: "POST",
crossDomain: true,
cache: false,
data: {
security: candidates.ajax_nonce,
action: 'SendToFormApi',
data: dataForm
},
dataType: 'json',
success: function (data, status, xhttp) {
// event.preventDefault();
if (data === true) {
window.location = candidates.merci_page_url;
} else {
window.location.href = candidates.error_page_url;
$("form").trigger('reset')
}
},
}
);
});
Callback function
function SendToFormApi_callback()
{
$formRandyValues = $_POST['data'];
$virtualagencyApiEmail = new virtualagencyApiEmail();
$result = $virtualagencyApiEmail->NyFormApi($formRandyValues);
$response = $virtualagencyApiEmail->NyFormApiCall($result,$formMyValues['id']);
$code = wp_remote_retrieve_response_code($response);
// if code 503 == service unavailable
// if code 401 == auth fail
// if code 400 == object fail
// if code 201 == success response
if ($code === 201) {
echo json_encode(true);
wp_die();
} else {
echo json_encode(false);
wp_die();
}
}
add_action('wp_ajax_SendToFormApi', 'SendToFormApi_callback', 1);
add_action('wp_ajax_nopriv_SendToFormApi', 'SendToFormApi_callback', 1);
public function NyFormApi($params): array
{
$uuidId = $params['id'] ?? $this->getUid();
$position_criteria_object = new Position_Criteria();
$position_criteria_object->type = 'string';
$position_criteria_object->label = 'besoin';
$position_criteria_object->question = 'votre_besoin';
$position_criteria_object->answer = $params['votreBesoin'];
$position_criteria_object->value = $params['votreBesoin'];
$origin_object = new Position_Criteria();
$origin_object->type = 'string';
$origin_object->label = 'origin';
$origin_object->question = 'candidature_oringin';
$origin_object->answer = 'My form';
$origin_object->value = 'My form';
$secteur_object = new Position_Criteria();
$secteur_object->type = 'string';
$secteur_object->label = 'secteur';
$secteur_object->question = 'secteur';
$secteur_object->answer = $params['secteur'];
$secteur_object->value = $params['secteur'];
$region_object = new Position_Criteria();
$region_object->type = 'string';
$region_object->label = 'region';
$region_object->question = 'region';
$region_object->answer = $params['region'];
$region_object->value = $params['region'];
$metier_object = new Position_Criteria();
$metier_object->type = 'string';
$metier_object->label = 'metier';
$metier_object->question = 'metier';
$metier_object->answer = $params['metier'];
$metier_object->value = $params['metier'];
$talent_object = new Talent();
$talent_object->id = $uuidId;
$talent_object->firstName = $params['firstName'];
$talent_object->lastName = $params['lastName'];
$talent_object->email = $params['email'];
$talent_object->phone = $params['phone'];
if(empty($params['qualificationCode'])){
$qualificationCode = "none";
} else {
$qualificationCode = $params['qualificationCode'];
}
return array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode($this->keyEncoded)
),
'body' => array(
'id' => $uuidId, //$params['id'], // str
'workTeamId' => $params['postClient'], // str
'priority' => 1, // int
'positionCriteria' => array(
$position_criteria_object,
$origin_object,
$secteur_object,
$region_object,
$metier_object
), // [{...},{...},...]
'occupationCode' => $qualificationCode, // str,
'occupationLabel' => $params['qualification'], // str
'talent' => $talent_object, // { key = value, ... }
)
);
}
public function MyFormApiCall($params, $id)
{
$url = $this->apiPathRandy . "/" . $id;
return wp_remote_post($url, $params);
}
// Get an RFC-4122 compliant globaly unique identifier
private function getUid(): string
{
$data = PHP_MAJOR_VERSION < 7 ? openssl_random_pseudo_bytes(16) : random_bytes(16);
$data[6] = chr(ord($data[6]) & 0x0f | 0x40); // Set version to 0100
$data[8] = chr(ord($data[8]) & 0x3f | 0x80); // Set bits 6-7 to 10
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
}
After reading and trying some solutions that i found, no of them work in my case.
Thank you for your help.
(note: there are some vars names that were changed for privacy)
I would remove all javascript from the form and do
if ($code === 201) {
header("location: merci.html");
wp_die();
} else {
header("location: erreur.html");
wp_die();
}

How to fix Stripe Error: Fatal error: Uncaught Stripe\Error\InvalidRequest: Must provide source or customer...?

Just wondering if anyone has any idea how to fix this error as I'm not sure. I'm aware there are similar questions but their full error is different.
Full Error HERE:
Fatal error: Uncaught Stripe\Error\InvalidRequest: Must provide source or customer. in /customers/8/7/b/exammarked.com/httpd.www/stripe/lib/ApiRequestor.php:110 from API request 'req_N9vZa4brfYHaam' Stack trace: #0 /customers/8/7/b/exammarked.com/httpd.www/stripe/lib/ApiRequestor.php(275): Stripe\ApiRequestor->handleApiError('{\n "error": {\n...', 400, Array, Array) #1 /customers/8/7/b/exammarked.com/httpd.www/stripe/lib/ApiRequestor.php(65): Stripe\ApiRequestor->_interpretResponse('{\n "error": {\n...', 400, Array) #2 /customers/8/7/b/exammarked.com/httpd.www/stripe/lib/ApiResource.php(120): Stripe\ApiRequestor->request('post', '/v1/charges', Array, Array) #3 /customers/8/7/b/exammarked.com/httpd.www/stripe/lib/ApiResource.php(159): Stripe\ApiResource::_staticRequest('post', '/v1/charges', Array, NULL) #4 /customers/8/7/b/exammarked.com/httpd.www/stripe/lib/Charge.php(74): Stripe\ApiResource::_create(Array, NULL) #5 /customers/8/7/b/exammarked.com/httpd.www/charge.php(17): Stripe\Charge::create(Array) #6 {main} throw in /customers/8/7/b/exammarked.com/httpd.www/stripe/lib/ApiRequestor.php on line 110
index.js
'use strict';
var stripe = Stripe('*****');
function registerElements(elements, exampleName) {
var formClass = '.' + exampleName;
var example = document.querySelector(formClass);
var form = example.querySelector('form');
var resetButton = example.querySelector('a.reset');
var error = form.querySelector('.error');
var errorMessage = error.querySelector('.message');
function enableInputs() {
Array.prototype.forEach.call(
form.querySelectorAll(
"input[type='text'], input[type='email'], input[type='tel']"
),
function(input) {
input.removeAttribute('disabled');
}
);
}
function disableInputs() {
Array.prototype.forEach.call(
form.querySelectorAll(
"input[type='text'], input[type='email'], input[type='tel']"
),
function(input) {
input.setAttribute('disabled', 'true');
}
);
}
function triggerBrowserValidation() {
// The only way to trigger HTML5 form validation UI is to fake a user submit
// event.
var submit = document.createElement('input');
submit.type = 'submit';
submit.style.display = 'none';
form.appendChild(submit);
submit.click();
submit.remove();
}
// Listen for errors from each Element, and show error messages in the UI.
var savedErrors = {};
elements.forEach(function(element, idx) {
element.on('change', function(event) {
if (event.error) {
error.classList.add('visible');
savedErrors[idx] = event.error.message;
errorMessage.innerText = event.error.message;
} else {
savedErrors[idx] = null;
// Loop over the saved errors and find the first one, if any.
var nextError = Object.keys(savedErrors)
.sort()
.reduce(function(maybeFoundError, key) {
return maybeFoundError || savedErrors[key];
}, null);
if (nextError) {
// Now that they've fixed the current error, show another one.
errorMessage.innerText = nextError;
} else {
// The user fixed the last error; no more errors.
error.classList.remove('visible');
}
}
});
});
// Listen on the form's 'submit' handler...
form.addEventListener('submit', function(e) {
e.preventDefault();
// Trigger HTML5 validation UI on the form if any of the inputs fail
// validation.
var plainInputsValid = true;
Array.prototype.forEach.call(form.querySelectorAll('input'), function(
input
) {
if (input.checkValidity && !input.checkValidity()) {
plainInputsValid = false;
return;
}
});
if (!plainInputsValid) {
triggerBrowserValidation();
return;
}
// Show a loading screen...
example.classList.add('submitting');
// Disable all inputs.
disableInputs();
// Gather additional customer data we may have collected in our form.
var name = form.querySelector('#' + exampleName + '-name');
var address1 = form.querySelector('#' + exampleName + '-address');
var city = form.querySelector('#' + exampleName + '-city');
var state = form.querySelector('#' + exampleName + '-state');
var zip = form.querySelector('#' + exampleName + '-zip');
var additionalData = {
name: name ? name.value : undefined,
address_line1: address1 ? address1.value : undefined,
address_city: city ? city.value : undefined,
address_state: state ? state.value : undefined,
address_zip: zip ? zip.value : undefined,
};
// Use Stripe.js to create a token. We only need to pass in one Element
// from the Element group in order to create a token. We can also pass
// in the additional customer data we collected in our form.
stripe.createToken(elements[0], additionalData).then(function(result) {
// Stop loading!
example.classList.remove('submitting');
if (result.token) {
// If we received a token, show the token ID.
example.querySelector('.token').innerText = result.token.id;
example.classList.add('submitted');
} else {
// Otherwise, un-disable inputs.
enableInputs();
}
});
});
resetButton.addEventListener('click', function(e) {
e.preventDefault();
// Resetting the form (instead of setting the value to `''` for each input)
// helps us clear webkit autofill styles.
form.reset();
// Clear each Element.
elements.forEach(function(element) {
element.clear();
});
// Reset error state as well.
error.classList.remove('visible');
// Resetting the form does not un-disable inputs, so we need to do it separately:
enableInputs();
example.classList.remove('submitted');
});
}
Other JS file:
(function() {
'use strict';
var stripe = Stripe('*****');
var elements = stripe.elements();
var elementStyles = {
base: {
color: '#555',
fontWeight: 400,
fontSize: '15px',
fontSmoothing: 'antialiased',
':focus': {
color: '#424770',
},
'::placeholder': {
color: '#555',
},
':focus::placeholder': {
color: '#CFD7DF',
},
},
invalid: {
color: '#555',
':focus': {
color: '#FA755A',
},
'::placeholder': {
color: '#FFCCA5',
},
},
};
var elementClasses = {
focus: 'focus',
empty: 'empty',
invalid: 'invalid',
};
var cardNumber = elements.create('cardNumber', {
style: elementStyles,
classes: elementClasses,
placeholder: "Card Number",
});
cardNumber.mount('#example3-card-number');
var cardExpiry = elements.create('cardExpiry', {
style: elementStyles,
classes: elementClasses,
placeholder: "Expiry (MM/YY)",
});
cardExpiry.mount('#example3-card-expiry');
var cardCvc = elements.create('cardCvc', {
style: elementStyles,
classes: elementClasses,
placeholder: "Security Code (CVC)",
});
cardCvc.mount('#example3-card-cvc');
registerElements([cardNumber, cardExpiry, cardCvc], 'example3');
})();
APIRESOURCE.PHP
<?php
namespace Stripe;
/**
* Class ApiResource
*
* #package Stripe
*/
abstract class ApiResource extends StripeObject
{
private static $HEADERS_TO_PERSIST = array('Stripe-Account' => true, 'Stripe-Version' => true);
public static function baseUrl()
{
return Stripe::$apiBase;
}
/**
* #return ApiResource The refreshed resource.
*/
public function refresh()
{
$requestor = new ApiRequestor($this->_opts->apiKey, static::baseUrl());
$url = $this->instanceUrl();
list($response, $this->_opts->apiKey) = $requestor->request(
'get',
$url,
$this->_retrieveOptions,
$this->_opts->headers
);
$this->setLastResponse($response);
$this->refreshFrom($response->json, $this->_opts);
return $this;
}
/**
* #return string The name of the class, with namespacing and underscores
* stripped.
*/
public static function className()
{
$class = get_called_class();
// Useful for namespaces: Foo\Charge
if ($postfixNamespaces = strrchr($class, '\\')) {
$class = substr($postfixNamespaces, 1);
}
// Useful for underscored 'namespaces': Foo_Charge
if ($postfixFakeNamespaces = strrchr($class, '')) {
$class = $postfixFakeNamespaces;
}
if (substr($class, 0, strlen('Stripe')) == 'Stripe') {
$class = substr($class, strlen('Stripe'));
}
$class = str_replace('_', '', $class);
$name = urlencode($class);
$name = strtolower($name);
return $name;
}
/**
* #return string The endpoint URL for the given class.
*/
public static function classUrl()
{
$base = static::className();
return "/v1/${base}s";
}
/**
* #return string The instance endpoint URL for the given class.
*/
public static function resourceUrl($id)
{
if ($id === null) {
$class = get_called_class();
$message = "Could not determine which URL to request: "
. "$class instance has invalid ID: $id";
throw new Error\InvalidRequest($message, null);
}
$id = Util\Util::utf8($id);
$base = static::classUrl();
$extn = urlencode($id);
return "$base/$extn";
}
/**
* #return string The full API URL for this API resource.
*/
public function instanceUrl()
{
return static::resourceUrl($this['id']);
}
protected static function _validateParams($params = null)
{
if ($params && !is_array($params)) {
$message = "You must pass an array as the first argument to Stripe API "
. "method calls. (HINT: an example call to create a charge "
. "would be: \"Stripe\\Charge::create(array('amount' => 100, "
. "'currency' => 'usd', 'card' => array('number' => "
. "4242424242424242, 'exp_month' => 5, 'exp_year' => 2015)))\")";
throw new Error\Api($message);
}
}
protected function _request($method, $url, $params = array(), $options = null)
{
$opts = $this->_opts->merge($options);
list($resp, $options) = static::_staticRequest($method, $url, $params, $opts);
$this->setLastResponse($resp);
return array($resp->json, $options);
}
protected static function _staticRequest($method, $url, $params, $options)
{
$opts = Util\RequestOptions::parse($options);
$requestor = new ApiRequestor($opts->apiKey, static::baseUrl());
list($response, $opts->apiKey) = $requestor->request($method, $url, $params, $opts->headers);
foreach ($opts->headers as $k => $v) {
if (!array_key_exists($k, self::$HEADERS_TO_PERSIST)) {
unset($opts->headers[$k]);
}
}
return array($response, $opts);
}
protected static function _retrieve($id, $options = null)
{
$opts = Util\RequestOptions::parse($options);
$instance = new static($id, $opts);
$instance->refresh();
return $instance;
}
protected static function _all($params = null, $options = null)
{
self::_validateParams($params);
$url = static::classUrl();
list($response, $opts) = static::_staticRequest('get', $url, $params, $options);
$obj = Util\Util::convertToStripeObject($response->json, $opts);
if (!is_a($obj, 'Stripe\\Collection')) {
$class = get_class($obj);
$message = "Expected type \"Stripe\\Collection\", got \"$class\" instead";
throw new Error\Api($message);
}
$obj->setLastResponse($response);
$obj->setRequestParams($params);
return $obj;
}
protected static function _create($params = null, $options = null)
{
self::_validateParams($params);
$url = static::classUrl();
list($response, $opts) = static::_staticRequest('post', $url, $params, $options);
$obj = Util\Util::convertToStripeObject($response->json, $opts);
$obj->setLastResponse($response);
return $obj;
}
/**
* #param string $id The ID of the API resource to update.
* #param array|null $params
* #param array|string|null $opts
*
* #return ApiResource the updated API resource
*/
protected static function _update($id, $params = null, $options = null)
{
self::_validateParams($params);
$url = static::resourceUrl($id);
list($response, $opts) = static::_staticRequest('post', $url, $params, $options);
$obj = Util\Util::convertToStripeObject($response->json, $opts);
$obj->setLastResponse($response);
return $obj;
}
protected function _save($options = null)
{
$params = $this->serializeParameters();
if (count($params) > 0) {
$url = $this->instanceUrl();
list($response, $opts) = $this->_request('post', $url, $params, $options);
$this->refreshFrom($response, $opts);
}
return $this;
}
protected function _delete($params = null, $options = null)
{
self::_validateParams($params);
$url = $this->instanceUrl();
list($response, $opts) = $this->_request('delete', $url, $params, $options);
$this->refreshFrom($response, $opts);
return $this;
}
}
APIREQUESTOR.PHP
<?php
namespace Stripe;
/**
* Class ApiRequestor
*
* #package Stripe
*/
class ApiRequestor
{
private $_apiKey;
private $_apiBase;
private static $_httpClient;
public function __construct($apiKey = null, $apiBase = null)
{
$this->_apiKey = $apiKey;
if (!$apiBase) {
$apiBase = Stripe::$apiBase;
}
$this->_apiBase = $apiBase;
}
private static function _encodeObjects($d)
{
if ($d instanceof ApiResource) {
return Util\Util::utf8($d->id);
} elseif ($d === true) {
return 'true';
} elseif ($d === false) {
return 'false';
} elseif (is_array($d)) {
$res = array();
foreach ($d as $k => $v) {
$res[$k] = self::_encodeObjects($v);
}
return $res;
} else {
return Util\Util::utf8($d);
}
}
/**
* #param string $method
* #param string $url
* #param array|null $params
* #param array|null $headers
*
* #return array An array whose first element is an API response and second
* element is the API key used to make the request.
*/
public function request($method, $url, $params = null, $headers = null)
{
if (!$params) {
$params = array();
}
if (!$headers) {
$headers = array();
}
list($rbody, $rcode, $rheaders, $myApiKey) =
$this->_requestRaw($method, $url, $params, $headers);
$json = $this->_interpretResponse($rbody, $rcode, $rheaders);
$resp = new ApiResponse($rbody, $rcode, $rheaders, $json);
return array($resp, $myApiKey);
}
/**
* #param string $rbody A JSON string.
* #param int $rcode
* #param array $rheaders
* #param array $resp
*
* #throws Error\InvalidRequest if the error is caused by the user.
* #throws Error\Authentication if the error is caused by a lack of
* permissions.
* #throws Error\Permission if the error is caused by insufficient
* permissions.
* #throws Error\Card if the error is the error code is 402 (payment
* required)
* #throws Error\RateLimit if the error is caused by too many requests
* hitting the API.
* #throws Error\Api otherwise.
*/
public function handleApiError($rbody, $rcode, $rheaders, $resp)
{
if (!is_array($resp) || !isset($resp['error'])) {
$msg = "Invalid response object from API: $rbody "
. "(HTTP response code was $rcode)";
throw new Error\Api($msg, $rcode, $rbody, $resp, $rheaders);
}
$error = $resp['error'];
$msg = isset($error['message']) ? $error['message'] : null;
$param = isset($error['param']) ? $error['param'] : null;
$code = isset($error['code']) ? $error['code'] : null;
switch ($rcode) {
case 400:
// 'rate_limit' code is deprecated, but left here for backwards compatibility
// for API versions earlier than 2015-09-08
if ($code == 'rate_limit') {
throw new Error\RateLimit($msg, $param, $rcode, $rbody, $resp, $rheaders);
}
// intentional fall-through
case 404:
throw new Error\InvalidRequest($msg, $param, $rcode, $rbody, $resp, $rheaders);
case 401:
throw new Error\Authentication($msg, $rcode, $rbody, $resp, $rheaders);
case 402:
throw new Error\Card($msg, $param, $code, $rcode, $rbody, $resp, $rheaders);
case 403:
throw new Error\Permission($msg, $rcode, $rbody, $resp, $rheaders);
case 429:
throw new Error\RateLimit($msg, $param, $rcode, $rbody, $resp, $rheaders);
default:
throw new Error\Api($msg, $rcode, $rbody, $resp, $rheaders);
}
}
private static function _formatAppInfo($appInfo)
{
if ($appInfo !== null) {
$string = $appInfo['name'];
if ($appInfo['version'] !== null) {
$string .= '/' . $appInfo['version'];
}
if ($appInfo['url'] !== null) {
$string .= ' (' . $appInfo['url'] . ')';
}
return $string;
} else {
return null;
}
}
private static function _defaultHeaders($apiKey)
{
$appInfo = Stripe::getAppInfo();
$uaString = 'Stripe/v1 PhpBindings/' . Stripe::VERSION;
$langVersion = phpversion();
$uname = php_uname();
$httplib = 'unknown';
$ssllib = 'unknown';
if (function_exists('curl_version')) {
$curlVersion = curl_version();
$httplib = 'curl ' . $curlVersion['version'];
$ssllib = $curlVersion['ssl_version'];
}
$appInfo = Stripe::getAppInfo();
$ua = array(
'bindings_version' => Stripe::VERSION,
'lang' => 'php',
'lang_version' => $langVersion,
'publisher' => 'stripe',
'uname' => $uname,
'httplib' => $httplib,
'ssllib' => $ssllib,
);
if ($appInfo !== null) {
$uaString .= ' ' . self::_formatAppInfo($appInfo);
$ua['application'] = $appInfo;
}
$defaultHeaders = array(
'X-Stripe-Client-User-Agent' => json_encode($ua),
'User-Agent' => $uaString,
'Authorization' => 'Bearer ' . $apiKey,
);
return $defaultHeaders;
}
private function _requestRaw($method, $url, $params, $headers)
{
$myApiKey = $this->_apiKey;
if (!$myApiKey) {
$myApiKey = Stripe::$apiKey;
}
if (!$myApiKey) {
$msg = 'No API key provided. (HINT: set your API key using '
. '"Stripe::setApiKey(<API-KEY>)". You can generate API keys from '
. 'the Stripe web interface. See https://stripe.com/api for '
. 'details, or email support#stripe.com if you have any questions.';
throw new Error\Authentication($msg);
}
$absUrl = $this->_apiBase.$url;
$params = self::_encodeObjects($params);
$defaultHeaders = $this->_defaultHeaders($myApiKey);
if (Stripe::$apiVersion) {
$defaultHeaders['Stripe-Version'] = Stripe::$apiVersion;
}
if (Stripe::$accountId) {
$defaultHeaders['Stripe-Account'] = Stripe::$accountId;
}
$hasFile = false;
$hasCurlFile = class_exists('\CURLFile', false);
foreach ($params as $k => $v) {
if (is_resource($v)) {
$hasFile = true;
$params[$k] = self::_processResourceParam($v, $hasCurlFile);
} elseif ($hasCurlFile && $v instanceof \CURLFile) {
$hasFile = true;
}
}
if ($hasFile) {
$defaultHeaders['Content-Type'] = 'multipart/form-data';
} else {
$defaultHeaders['Content-Type'] = 'application/x-www-form-urlencoded';
}
$combinedHeaders = array_merge($defaultHeaders, $headers);
$rawHeaders = array();
foreach ($combinedHeaders as $header => $value) {
$rawHeaders[] = $header . ': ' . $value;
}
list($rbody, $rcode, $rheaders) = $this->httpClient()->request(
$method,
$absUrl,
$rawHeaders,
$params,
$hasFile
);
return array($rbody, $rcode, $rheaders, $myApiKey);
}
private function _processResourceParam($resource, $hasCurlFile)
{
if (get_resource_type($resource) !== 'stream') {
throw new Error\Api(
'Attempted to upload a resource that is not a stream'
);
}
$metaData = stream_get_meta_data($resource);
if ($metaData['wrapper_type'] !== 'plainfile') {
throw new Error\Api(
'Only plainfile resource streams are supported'
);
}
if ($hasCurlFile) {
// We don't have the filename or mimetype, but the API doesn't care
return new \CURLFile($metaData['uri']);
} else {
return '#'.$metaData['uri'];
}
}
private function _interpretResponse($rbody, $rcode, $rheaders)
{
$resp = json_decode($rbody, true);
$jsonError = json_last_error();
if ($resp === null && $jsonError !== JSON_ERROR_NONE) {
$msg = "Invalid response body from API: $rbody "
. "(HTTP response code was $rcode, json_last_error() was $jsonError)";
throw new Error\Api($msg, $rcode, $rbody);
}
if ($rcode < 200 || $rcode >= 300) {
$this->handleApiError($rbody, $rcode, $rheaders, $resp);
}
return $resp;
}
public static function setHttpClient($client)
{
self::$_httpClient = $client;
}
private function httpClient()
{
if (!self::$_httpClient) {
self::$_httpClient = HttpClient\CurlClient::instance();
}
return self::$_httpClient;
}
}
CHARGE.PHP
<?php
//include Stripe library
require_once ('./stripe/init.php');
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
\Stripe\Stripe::setApiKey("sk_test_jfrwNbzP7kUm6kbXSHHDkqce");
// Token is created using Checkout or Elements!
// Get the payment token ID submitted by the form:
$token = $_POST['stripeToken'];
$charge = \Stripe\Charge::create([
'amount' => 999,
'currency' => 'usd',
'description' => 'Example charge',
'source' => $token,
]);
?>

A console application to get a web page resource, using c# (javascript may cause this)

Aim: To download a website source with using a console application. You can find the used class in the program below.
Question: I use the code below to download a data (source) of a web page. Imagine you use chrome; If you enter first this query string, the web page itself redirects you a view HTML page and you see the data.
Entering this URL, to show the results it redirects itself to second page below. I make it by using javascript.
www.xyz.com/aaa.html?search=aaa&id=1
it redirects here: www.xyz.com/ViewResult.html
In an explorer, It works fine . I see 4 HTML tables inside the page when I use google chrome view source option. Bu in my application I see only two tables of the 4 . The two tables inside the web page is missing.(the missing two tables are the second and third.)
How can I overcome to this problem? I want to get the source of the page as I see in chrome.
Bonus informations: There is no iframe.
The particular Code :
string url = "www.xyz.com/aaa.html?search=aaa&id=1";
WebPage pG = ss.RequestPage(url, "", "GET");
pG = ss.RequestPage("www.xyz.com/ViewResult.html");
string source= pG.Html;
public WebPage RequestPage(Uri url, string content, string method, string contentType)
{
string htmlResult;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
HttpWebResponse response = null;
ASCIIEncoding encoding = new ASCIIEncoding();
byte[] contentData = encoding.GetBytes(content);
request.Proxy = Proxy;
request.Timeout = 60000;
request.Method = method;
request.AllowAutoRedirect = false; // false
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
request.Referer = LastUrl;
request.KeepAlive = true; //false,
request.UserAgent = UserAgent;
request.Headers.Add("Accept-Language", "en-us,en;q=0.5");
//request.Headers.Add("UA-CPU", "x86");
request.Headers.Add("Cache-Control", "no-cache");
request.Headers.Add("Accept-Encoding", "gzip,deflate");
String cookieString = "";
foreach (KeyValuePair<String, String> cookiePair in Cookies)
cookieString += cookiePair.Key + "=" + cookiePair.Value + ";";
if (cookieString.Length > 2)
{
String cookie = cookieString.Substring(0, cookieString.Length - 1);
request.Headers.Add("Cookie", cookie);
}
if (method == "POST")
{
request.ContentLength = contentData.Length;
request.ContentType = contentType;
Stream contentWriter = request.GetRequestStream();
contentWriter.Write(contentData, 0, contentData.Length);
contentWriter.Close();
}
int attempts = 0;
while (true)
{
try
{
response = (HttpWebResponse)request.GetResponse();
if (response == null)
throw new WebException();
break;
}
catch (WebException)
{
if (response != null)
response.Close();
if (attempts == PageReattempts)
{
throw;
}
else { }
// Wait three seconds before trying again
Thread.Sleep(3000);
}
attempts += 1;
}
// Tokenize cookies
if (response.Headers["Set-Cookie"] != null)
{
String headers = response.Headers["Set-Cookie"].Replace("path=/,", ";").Replace("HttpOnly,", "");
foreach (String cookie in headers.Split(';'))
{
if (cookie.Contains("="))
{
String[] splitCookie = cookie.Split('=');
String cookieKey = splitCookie[0].Trim();
String cookieValue = splitCookie[1].Trim();
if (Cookies.ContainsKey(cookieKey))
Cookies[cookieKey] = cookieValue;
else
Cookies.Add(cookieKey, cookieValue);
}
else
{
if (Cookies.ContainsKey(cookie))
Cookies[cookie] = "";
else
Cookies.Add(cookie, "");
}
}
}
htmlResult = ReadResponseStream(response);
response.Close();
if (response.Headers["Location"] != null)
{
response.Close();
Thread.Sleep(1500);
String newLocation = response.Headers["Location"];
WebPage result = RequestPage(newLocation);
return new WebPage(result.Html, new WebPage(htmlResult));
}
LastUrl = url.ToString();
return new WebPage(htmlResult);
}
1-WebBrowser :
public class ExtendedWebBrowser : System.Windows.Forms.WebBrowser
{
public ExtendedWebBrowser()
{
// Ensure that ScriptErrorsSuppressed is set to false.
this.ScriptErrorsSuppressed = true;
this.ProgressChanged += ExtendedWebBrowser_ProgressChanged;
}
private void ExtendedWebBrowser_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
{
// InjectAlertBlocker();
string alertBlocker = #"window.alert = function () { };
window.print = function () { };
window.open = function () { };
window.onunload = function () { };
window.onbeforeunload = function () { };";
var webBrowser = sender as WebBrowser;
webBrowser?.Document?.InvokeScript("execScript", new Object[] { alertBlocker, "JavaScript" });
this.Document?.InvokeScript("execScript", new Object[] { alertBlocker, "JavaScript" });
}
public void NavigationWaitToComplete(string url)
{
bool complete = false;
NavigationAsync(url).ContinueWith((t) => complete = true);
while (!complete)
{
System.Windows.Forms.Application.DoEvents();
}
}
public void NavigationWaitToComplete(string url, string targetFrameName, byte[] postData, string additionalHeaders)
{
bool complete = false;
NavigationAsync(url, targetFrameName, postData, additionalHeaders).ContinueWith((t) => complete = true);
while (!complete)
{
System.Windows.Forms.Application.DoEvents();
}
}
public async Task NavigationAsync(string url, string targetFrameName, byte[] postData, string additionalHeaders)
{
TaskCompletionSource<bool> tcsNavigation = new TaskCompletionSource<bool>(); ;
TaskCompletionSource<bool> tcsDocument = new TaskCompletionSource<bool>(); ;
Navigated += (s, e) =>
{
if (tcsNavigation.Task.IsCompleted)
return;
tcsNavigation.SetResult(true);
};
DocumentCompleted += (s, e) =>
{
if (ReadyState != WebBrowserReadyState.Complete)
return;
if (tcsDocument.Task.IsCompleted)
return;
tcsDocument.SetResult(true);
};
Navigate(url, targetFrameName, postData, additionalHeaders);
await tcsNavigation.Task;
// navigation completed, but the document may still be loading
await tcsDocument.Task;
// the document has been fully loaded, you can access DOM here
}
public async Task NavigationAsync(string url)
{
TaskCompletionSource<bool> tcsNavigation = new TaskCompletionSource<bool>(); ;
TaskCompletionSource<bool> tcsDocument = new TaskCompletionSource<bool>(); ;
Navigated += (s, e) =>
{
if (tcsNavigation.Task.IsCompleted)
return;
tcsNavigation.SetResult(true);
};
DocumentCompleted += (s, e) =>
{
if (ReadyState != WebBrowserReadyState.Complete)
return;
if (tcsDocument.Task.IsCompleted)
return;
tcsDocument.SetResult(true);
};
Navigate(url);
await tcsNavigation.Task;
// navigation completed, but the document may still be loading
await tcsDocument.Task;
// the document has been fully loaded, you can access DOM here
}
}
Calling:
var browser = new ExtendedWebBrowser();
browser.NavigationWaitToComplete("www.xyz.com/aaa.html?search=aaa&id=1");
var html = browser.Document.Body.OuterHtml();
2-CefSharp.OffScreen
private async Task<string> RequestPageAsync(string url, string cachePath, double zoomLevel)
{
var tcs = new TaskCompletionSource<string>();
var browserSettings = new BrowserSettings();
//Reduce rendering speed to one frame per second so it's easier to take screen shots
browserSettings.WindowlessFrameRate = 1;
var requestContextSettings = new RequestContextSettings { CachePath = cachePath };
// RequestContext can be shared between browser instances and allows for custom settings
// e.g. CachePath
using (var requestContext = new RequestContext(requestContextSettings))
using (var browser = new ChromiumWebBrowser(url, browserSettings, requestContext))
{
if (zoomLevel > 1)
{
browser.FrameLoadStart += (s, argsi) =>
{
var b = (ChromiumWebBrowser)s;
if (argsi.Frame.IsMain)
{
b.SetZoomLevel(zoomLevel);
}
};
}
browser.FrameLoadEnd += (s, argsi) =>
{
var b = (ChromiumWebBrowser)s;
if (argsi.Frame.IsMain)
{
b.GetSourceAsync().ContinueWith(taskHtml =>
{
tcs.TrySetResult(taskHtml.Result);
});
}
};
}
return tcs.Task.Result;
}
Calling :
RequestPageAsync("www.xyz.com/aaa.html?search=aaa&id=1", "cachePath1", 1.0);

How To print a result of ActionResult if it is Done

How to print a result after calling ActionResult?
For example, here is my call from a view:
<a title="Add To Read Later"
target="_blank"
href="#(Url.Action("Insert", "ReadLater",new {Book_id=Model.Book.Book_id }))">
<small class="fa fa-2x fa-plus"></small>
</a>
And here is my ReadLaterController method:
public ActionResult Insert(int? Book_id)
{
if (User.Identity.IsAuthenticated)
{
var x = User.Identity.GetUserId();
var result = db.Books.Where(p => p.Book_id == Book_id).Single();
if(result.Book_id == Book_id)
{
var IsExists = db.ReadLaters.FirstOrDefault(t => t.Book_Id == result.Book_id && t.User_Id==x);
if (IsExists == null)
{
ReadLater ReadL = new ReadLater()
{
Book_Id = result.Book_id,
User_Id = x.ToString()
};
db.ReadLaters.Add(ReadL);
int state = db.SaveChanges();
if (state == 1)
{
return new JavaScriptResult { Script = "alert('Successfully Added');" };
}
}
else
{
return new JavaScriptResult { Script = "alert('You Added This book Before');" };
}
}
}
return new JavaScriptResult { Script = "alert('Not Added');" };
}
As you see, if the content was added to database, I want to show an alert in the same page from which I called the controller, saying: if the data added or not added or already added depend on the method result ....
Right now it works by going to the method URL and printing the result there without JavaScript effects, just as text:
http://localhost:49119/ReadLater/Insert?Book_id=19
And the result in that URL is:
alert('You Added This book Before');
Here is an AJAX example you could use. I put it as a button.. It could be whatever you want though.
Html
<button data-id="#Model.Book.Book_id" class="insertButton fa fa-2x fa-plus">Add to Read Later</button>
Ajax
$('.insertButton').click(function () {
var myId = $(this).data('id');
$.ajax({
type: "GET",
url: '#Url.Action("Insert","ReadLater")?Book_id=' + myId,
success: function (response) {
alert(response);
},
failure: function (response) {
alert("Failure");
}
});
});
Controller
[HttpGet]
public ActionResult Insert(int? Book_id)
{
if (User.Identity.IsAuthenticated)
{
var x = User.Identity.GetUserId();
var result = db.Books.Where(p => p.Book_id == Book_id).Single();
if (result.Book_id == Book_id)
{
var IsExists = db.ReadLaters.FirstOrDefault(t => t.Book_Id == result.Book_id && t.User_Id == x);
if (IsExists == null)
{
ReadLater ReadL = new ReadLater()
{
Book_Id = result.Book_id,
User_Id = x.ToString()
};
db.ReadLaters.Add(ReadL);
int state = db.SaveChanges();
if (state == 1)
{
return Content("Successfully Added");
}
}
else
{
return Content("You Added This book Before");
}
}
}
return Content("Not Added");
}

Read-Only Button for List Item in Sharepoint

I've got the following Sharepoint problem: I've created a Ribbon Button, which says "Read Only". When I am on a list, and check some items, I want to set those items to read only.
The ribbon button works great and when I am doing an alert or something, I get an answer. So this cannot be the problem. I did the following:
var listitem;
var roleAssgn;
var Assgn;
var selectedItems;
function readonly() {
selectedItems = SP.ListOperation.Selection.getSelectedItems();
var currentListGuid = SP.ListOperation.Selection.getSelectedList();
var context = SP.ClientContext.get_current();
var currentWeb = context.get_web();
var currentList = currentWeb.get_lists().getById(currentListGuid);
for (k in selectedItems) {
listitem = currentList.getItemById(selectedItems[k].id);
context.load(listitem, 'RoleAssignments');
context.executeQueryAsync(Function.createDelegate(this, this.readonlyPerItem), Function.createDelegate(this, this.failed));
}
}
function readonlyPerItem(sender, args) {
var k;
var Assgn;
var r;
context = SP.ClientContext.get_current();
roleAssgn = listitem.get_roleAssignments();
for(r in roleAssgn){
Assgn = roleAssgn[r];
alert("1");
context.load(Assgn, 'RoleDefinitionBindings');
alert("2");
context.executeQueryAsync(Function.createDelegate(this, this.readonlyPerRoleA), Function.createDelegate(this, this.failed));
}
}
function readonlyPerRoleA(sender, args) {
var bindings = Assgn.get_roleDefinitionBindings();
var member = Assgn.get_member();
}
function failed(sender, args) {
alert("FAIL");
}
This works great until it gets to the alerts. Alert-1 is working, but not Alert-2. The Debugger says: The object does not support the property "get_$h".
And that happens in the sp_runtime.js with:
SP.DataRetrievalWithExpressionString.$1Q_0(a.get_$h(),d)
I dont really see a problem. Is this a bug or is it just not possible?
Ok, I used another way to do this and wanted to let you know, how it worked for me. I used a JS in the Ribbon Menu to call another website, which is just an empty site. I added the parameters (listguid, siteurl and the itemid's comma-seperated).
Then that site just prints an "True" or "False". This response will be caught by my Ribbon JS and show some message if it worked or not. This is my Ribbon JS:
<CustomAction
Id="ReadOnlyButton"
RegistrationId="101"
RegistrationType="List"
Location="CommandUI.Ribbon"
Sequence="15"
Rights="ManageLists"
Title="Set Readonly">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition
Location="Ribbon.Documents.Manage.Controls._children">
<Button
Id="Ribbon.Documents.ReadOnly"
Command="ReadOnly"
Sequence="15"
Image16by16="/_layouts/1031/images/formatmap16x16.png"
Image16by16Left="-80"
Image16by16Top="-128"
Image32by32="/_layouts/1031/images/formatmap32x32.png"
Image32by32Left="-160"
Image32by32Top="-256"
Description="Read Only"
LabelText="Read Only"
TemplateAlias="o1"/>
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command="ReadOnly"
CommandAction="javascript:
var nid;
function getItemIds()
{
var itemIds = '';
var items = SP.ListOperation.Selection.getSelectedItems();
var item;
for(var i in items)
{
item = items[i];
if(itemIds != '')
{
itemIds = itemIds + ',';
}
itemIds = itemIds + item.id;
}
return itemIds;
}
function handleReadyStateChange()
{
if (client.readyState == 4)
{
if (client.status == 200)
{
SP.UI.Notify.removeNotification(nid);
if(client.responseText == 'True') {
nid = SP.UI.Status.addStatus('The Rights has been set successfully', '', true);
SP.UI.Status.setStatusPriColor(nid, 'green');
} else {
nid = SP.UI.Status.addStatus('Error while setting Rights', '', true);
SP.UI.Status.setStatusPriColor(nid, 'red');
}
window.setTimeout('SP.UI.Status.removeStatus(\'' + nid + '\')', 5000);
}
}
}
function invokeReadOnly()
{
var itemLength = 0;
var params = 'itemids=' + getItemIds();
for (var i=0;i<params.length;i++) { if (',' == params.substr(i,1)) { itemLength++; } }
if(itemLength > 0) {
nid = SP.UI.Notify.addNotification('Rights set for ' + (itemLength +1) + ' elements...', true);
} else {
nid = SP.UI.Notify.addNotification('Set Rights...', true);
}
var site='{SiteUrl}';
var url = site + '/_layouts/ReadOnly.aspx?listId={ListId}';
client = null;
client = new XMLHttpRequest();
client.onreadystatechange = handleReadyStateChange;
client.open('POST', url, true);
client.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
client.setRequestHeader('Content-length', params.length);
client.send(params);
}
invokeReadOnly();"
EnabledScript="javascript:
function enableReadOnly()
{
var items = SP.ListOperation.Selection.getSelectedItems();
return (items.length > 0);
}
enableReadOnly();"/>
</CommandUIHandlers>
</CommandUIExtension>
</CustomAction>
And this is my site behind it (ReadOnly.aspx):
protected void Page_Load(object sender, EventArgs e)
{
string itemidsAll = Page.Request["itemids"];
string listId = Page.Request["listId"];
bool set = true;
if (!String.IsNullOrEmpty(itemidsAll))
{
string[] itemIds = itemidsAll.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
int item = 0;
SPSite _site = null;
SPListItem spitem = null;
SPSecurity.RunWithElevatedPrivileges(delegate()
{
_site = new SPSite(SPContext.Current.Site.ID);
});
using (SPWeb web = _site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList doclib = SPContext.Current.Web.Lists.GetList(new Guid(listId), false);
foreach (string itemId in itemIds)
{
if (Int32.TryParse(itemId, out item))
{
spitem = doclib.GetItemById(item);
set &= SetItem(spitem, SPContext.Current, ref _site);
}
}
web.AllowUnsafeUpdates = false;
}
_site.Dispose();
}
Response.Clear();
Response.Write(set.ToString());
Response.End();
}
The SetItem-Method is for setting the Rights. You can use your own stuff there :)

Categories

Resources