text:
/*
 * .: >> semantic.h
 *
 * ?: Aristoteles Panaras "ale1ster"
 *    Alexandros Mavrogiannis "afein"
 * @: Mon 18 Mar 2013 04:10:23 PM EET
 *
 */

#include <stdlib.h>
#include <string.h>
#include <llvm-c/Core.h>
#include <llvm-c/Analysis.h>
#include "semantic.h"
#include "parser.h"
#include "general.h"
#include "error.h"
#include "ir.h"

extern LLVMBuilderRef builder;

//Returns a string representation of a type for error reporting.
const char *verbose_type (Type t) {
	char *res = new(35 * sizeof(char));
	if (t == typeInteger) {
		return "int";
	} else if (t == typeReal) {
		return "REAL";
	} else if (t == typeBoolean) {
		return "bool";
	} else if (t == typeChar) {
		return "char";
	} else if (t == typeVoid) {
		return "void";
	} else if (t->kind >= TYPE_ARRAY) {
		if (t->refType->kind == TYPE_ARRAY) {
			res = "multidimensional Array";
		} else {
			strcpy(res, verbose_type(t->refType));
			strcat(res, " array");
		}
	}
	return res;
}

//Evaluates constant operations between Reals.
void eval_real_op (RepReal left, RepReal right, const char *op, struct ast_node *res) {
	if (!strcmp(op, "*")) {
		res->type = typeReal;
		res->value.r = left * right;
	} else if (!strcmp(op, "/")) {
		res->type = typeReal;
		res->value.r = left / right;
	} else if (!strcmp(op, "+")) {
		res->type = typeReal;
		res->value.r = left + right;
	} else if (!strcmp(op, "-")) {
		res->type = typeReal;
		res->value.r = left - right;
	} else if (!strcmp(op, "<")) {
		res->type = typeBoolean;
		res->value.b = left < right;
	} else if (!strcmp(op, ">")) {
		res->type = typeBoolean;
		res->value.b = left < right;
	} else if (!strcmp(op, ">=")) {
		res->type = typeBoolean;
		res->value.b = left >= right;
	} else if (!strcmp(op, "<=")) {
		res->type = typeBoolean;
		res->value.b = left <= right;
	} else if (!strcmp(op, "==")) {
		res->type = typeBoolean;
		res->value.b = left == right;
	} else if (!strcmp(op, "!=")) {
		res->type = typeBoolean;
		res->value.b = left != right;
	} else {
		my_error(ERR_LV_ERR, "Cannot perform \"%s\" between Reals", op);
	}
}

//Evaluates constant operations between Integers.
void eval_int_op (RepInteger left, RepInteger right, const char *op, struct ast_node *res) {
	if (!strcmp(op, "*")) {
		res->type = typeInteger;
		res->value.i = left * right;
	} else if (!strcmp(op, "/")) {
		res->type = typeInteger;
		res->value.i = left / right;
	} else if (!strcmp(op, "+")) {
		res->type = typeInteger;
		res->value.i = left + right;
	} else if (!strcmp(op, "-")) {
		res->type = typeInteger;
		res->value.i = left - right;
	} else if (!strcmp(op, "%") || !strcmp(op, "MOD")) {
		res->type = typeInteger;
		res->value.i = left % right;
	} else if (!strcmp(op, "<")) {
		res->type = typeBoolean;
		res->value.b = left < right;
	} else if (!strcmp(op, ">")) {
		res->type = typeBoolean;
		res->value.b = left > right;
	} else if (!strcmp(op, "<=")) {
		res->type = typeBoolean;
		res->value.b = left <= right;
	} else if (!strcmp(op, ">=")) {
		res->type = typeBoolean;
		res->value.b = left >= right;
	} else if (!strcmp(op, "==")) {
		res->type = typeBoolean;
		res->value.b = left == right;
	} else if (!strcmp(op, "!=")) {
		res->type = typeBoolean;
		res->value.b = left != right;
	} else {
		my_error(ERR_LV_ERR, "Cannot perform \"%s\" between Integers", op);
	}
}

//Evaluates constant operations between Booleans.
void eval_bool_op (RepBoolean left, RepBoolean right, const char *op, struct ast_node *res) {
	res->type = typeBoolean;
	if (!strcmp(op, "==")) {
		res->value.b = left == right;
	} else if (!strcmp(op, "!=")) {
		res->value.b = left != right;
	} else if (!strcmp(op, "&&") || !strcmp(op,"and")) {
		res->value.b = left && right;
	} else if (!strcmp(op, "||") || !strcmp(op,"or")) {
		res->value.b = left || right;
	} else {
		my_error(ERR_LV_ERR, "Cannot perform \"%s\" between Booleans", op);
	}
}

//Evaluates and type checks a constant unary operator.
void eval_const_unop(struct ast_node *operand, const char *op, struct ast_node *res) {
	res->type = typeVoid; // could be changed to NULL
	if (!strcmp(op, "+")) {
		if (operand->type == typeInteger) {
			res->type = typeInteger;
			res->value.i = operand->value.i;
		} else if (operand->type == typeReal) {
			res->type = typeReal;
			res->value.r = operand->value.r;
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" on %s", op, verbose_type(operand->type));
		}
	} else if (!strcmp(op, "-")) {
		if (operand->type == typeInteger) {
			res->type = typeInteger;
			res->value.i = -(operand->value.i);
		} else if (operand->type == typeReal) {
			res->type = typeReal;
			res->value.r = -(operand->value.r);
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" on %s", op, verbose_type(operand->type));
		}
	} else if (!strcmp(op, "!") || !strcmp(op, "not")) {
		if (operand->type == typeBoolean) {
			res->type = typeBoolean;
			res->value.b = !(operand->value.b);
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" on %s", op, verbose_type(operand->type));
		}
	} else {
		my_error(ERR_LV_INTERN, "unreachable");
	}
}

//Type checks and produces IR for a unary operation.
void unop_IR(struct ast_node *operand, const char *op, struct ast_node *res) {
	res->type = typeVoid; // could be changed to NULL
	if (!strcmp(op, "+")) {
		if (operand->type == typeInteger) {
			res->type = typeInteger;
			res->Valref = operand->Valref;
		} else if (operand->type == typeReal) {
			res->type = typeReal;
			res->Valref = operand->Valref;
		} else if (operand->type == typeChar) {
			res->type = typeInteger;
			res->Valref = LLVMBuildZExt(builder, operand->Valref, LLVMInt32Type(), "zexttmp");
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" on %s", op, verbose_type(operand->type));
		}
	} else if (!strcmp(op, "-")) {
		if (operand->type == typeInteger) {
			res->type = typeInteger;
			res->Valref = LLVMBuildNSWNeg(builder, operand->Valref, "negtmp");
		} else if (operand->type == typeReal) {
			res->type = typeReal;
			res->Valref = LLVMBuildFNeg(builder, operand->Valref, "negtmp");
		} else if (operand->type == typeChar) {
			res->type = typeInteger;
			LLVMValueRef tmp = LLVMBuildZExt(builder, operand->Valref, \
											 LLVMInt32Type(), "zexttmp");
			res->Valref = LLVMBuildNUWNeg(builder, tmp, "negtmp");
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" on %s", op, verbose_type(operand->type));
		}
	} else if (!strcmp(op, "!") || !strcmp(op, "not")) {
		if (operand->type == typeBoolean) {
			res->type = typeBoolean;
			res->Valref = LLVMBuildNot(builder, operand->Valref, "nottmp");
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" on %s", op, verbose_type(operand->type));
		}
	} else {
		my_error(ERR_LV_INTERN, "unreachable");
	}
}

//Evaluates and Type checks a constant binop expression.
void eval_const_binop(struct ast_node *left, struct ast_node *right, const char *op, struct ast_node *res) {
	res->type = typeVoid; // could be changed to NULL
	if ((left->type == typeInteger) && (right->type == typeReal)) {
		eval_real_op((RepReal) left->value.i, right->value.r, op, res);

	} else if ((left->type == typeReal) && (right->type == typeInteger)) {
		eval_real_op(left->value.r, (RepReal) right->value.i, op, res);

	} else if ((left->type == typeChar) && (right->type == typeReal)) {
		eval_real_op((RepReal) left->value.c, right->value.r, op, res);

	} else if ((left->type == typeReal) && (right->type == typeChar)) {
		eval_real_op(left->value.r, (RepReal) right->value.c, op, res);

	} else if ((left->type == typeReal) && (right->type == typeReal)) {
		eval_real_op(left->value.r, right->value.r, op, res);

	} else if ((left->type == typeInteger) && (right->type == typeInteger)) {
		eval_int_op(left->value.i, right->value.i, op, res);

	} else if ((left->type == typeChar) && (right->type == typeInteger)) {
		eval_int_op((RepInteger) left->value.c, right->value.i, op, res);

	} else if ((left->type == typeInteger) && (right->type == typeChar)) {
		eval_int_op(left->value.i, (RepInteger) right->value.c, op, res);

	} else if ((left->type == typeChar) && (right->type == typeChar)) {
		eval_int_op((RepInteger) left->value.c, (RepInteger) right->value.c, op, res);

	} else if ((left->type == typeBoolean) && (right->type == typeBoolean)) {
		eval_bool_op(left->value.b, right->value.b, op, res);

	} else {
		my_error(ERR_LV_ERR, "Type mismatch on \"%s\" operator between %s and %s", \
				 op, verbose_type(left->type), verbose_type(right->type));
	}
}

// Produces IR for a binary operation on a specific type of pair operands
void op_IR(const char * op, LLVMValueRef left, LLVMValueRef right, Type t, LLVMValueRef * res) {
	/* TODO: signed operations? */
	if (t == typeReal) {
		if (!strcmp(op, "+")) {
			*res = LLVMBuildFAdd(builder, left, right, "addtmp");
		} else if (!strcmp(op, "-")) {
			*res = LLVMBuildFSub(builder, left, right, "subtmp");
		} else if (!strcmp(op, "*")) {
			*res = LLVMBuildFMul(builder, left, right, "multmp");
		} else if (!strcmp(op, "/")) {
			*res = LLVMBuildFDiv(builder, left, right, "divtmp");
		} else if (!strcmp(op, "<")) {
			*res = LLVMBuildFCmp(builder, LLVMRealOLT, left, right, "lesstmp");
		} else if (!strcmp(op, "<=")) {
			*res = LLVMBuildFCmp(builder, LLVMRealOLE, left, right, "leqtmp");
		} else if (!strcmp(op, ">")) {
			*res = LLVMBuildFCmp(builder, LLVMRealOGT, left, right, "greatmp");
		} else if (!strcmp(op, ">=")) {
			*res = LLVMBuildFCmp(builder, LLVMRealOGT, left, right, "greqtmp");
		} else if (!strcmp(op, "==")) {
			*res = LLVMBuildFCmp(builder, LLVMRealOEQ, left, right, "eqtmp");
		} else if (!strcmp(op, "!=")) {
			*res = LLVMBuildFCmp(builder, LLVMRealONE, left, right, "difftmp");
		}
	} else if (t == typeInteger) {
		if (!strcmp(op, "+")) {
			*res = LLVMBuildNSWAdd(builder, left, right, "addtmp");
		} else if (!strcmp(op, "-")) {
			*res = LLVMBuildNSWSub(builder, left, right, "subtmp");
		} else if (!strcmp(op, "*")) {
			*res = LLVMBuildMul(builder, left, right, "multmp");
		} else if (!strcmp(op, "/")) {
			*res = LLVMBuildSDiv(builder, left, right, "divtmp");
		} else if ((!strcmp(op, "%")) || (!strcmp(op, "MOD"))) {
			*res = LLVMBuildSRem(builder, left, right, "modtmp");
		} else if (!strcmp(op, "<")) {
			*res = LLVMBuildICmp(builder, LLVMIntSLT, left, right, "lesstmp");
		} else if (!strcmp(op, "<=")) {
			*res = LLVMBuildICmp(builder, LLVMIntSLE, left, right, "leqtmp");
		} else if (!strcmp(op, ">")) {
			*res = LLVMBuildICmp(builder, LLVMIntSGT, left, right, "greatmp");
		} else if (!strcmp(op, ">=")) {
			*res = LLVMBuildICmp(builder, LLVMIntSGE, left, right, "greqtmp");
		} else if (!strcmp(op, "==")) {
			*res = LLVMBuildICmp(builder, LLVMIntEQ, left, right, "eqtmp");
		} else if (!strcmp(op, "!=")) {
			*res = LLVMBuildICmp(builder, LLVMIntNE, left, right, "difftmp");
		}
	} else if (t == typeBoolean) {
		if (!strcmp(op, "==")) {
			*res = LLVMBuildICmp(builder, LLVMIntEQ, left, right, "eqtmp");
		} else if (!strcmp(op, "!=")) {
			*res = LLVMBuildICmp(builder, LLVMIntNE, left, right, "difftmp");
		} else if ((!strcmp(op, "&&")) || (!strcmp(op, "and"))) {
			*res = LLVMBuildAnd(builder, left, right, "andtmp");
		} else if ((!strcmp(op, "||")) || (!strcmp(op, "or"))) {
			*res = LLVMBuildOr(builder, left, right, "ortmp");
		}
	} else {
		my_error(ERR_LV_CRIT, "Internal error: invalid common operand type during binop IR");
	}
}

//Expr Binops - Create IR for casting to each.
void binop_IR(struct ast_node *left, struct ast_node *right, const char *op, struct ast_node *res) {
	LLVMValueRef tmp;
	res->type = typeVoid; // could be changed to NULL
	if ((left->type == typeInteger) && (right->type == typeReal)) {
		res->type = binop_type_check(op, typeReal);
		tmp = cast_compat(typeReal, typeInteger, left->Valref);
		op_IR(op, tmp, right->Valref, typeReal, &(res->Valref));
	} else if ((left->type == typeReal) && (right->type == typeInteger)) {
		res->type = binop_type_check(op, typeReal);
		tmp = cast_compat(typeReal, typeInteger, right->Valref);
		op_IR(op, left->Valref, tmp, typeReal, &(res->Valref));
	} else if ((left->type == typeChar) && (right->type == typeReal)) {
		res->type = binop_type_check(op, typeReal);
		tmp = cast_compat(typeReal, typeChar, left->Valref);
		op_IR(op, tmp, right->Valref, typeReal, &(res->Valref));
	} else if ((left->type == typeReal) && (right->type == typeChar)) {
		res->type = binop_type_check(op, typeReal);
		tmp = cast_compat(typeReal, typeChar, right->Valref);
		op_IR(op, left->Valref, tmp, typeReal, &(res->Valref));
	} else if ((left->type == typeReal) && (right->type == typeReal)) {
		res->type = binop_type_check(op, typeReal);
		op_IR(op, left->Valref, right->Valref, typeReal, &(res->Valref));
	} else if ((left->type == typeInteger) && (right->type == typeInteger)) {
		res->type = binop_type_check(op, typeInteger);
		op_IR(op, left->Valref, right->Valref, typeInteger, &(res->Valref));
	} else if ((left->type == typeChar) && (right->type == typeInteger)) {
		res->type = binop_type_check(op, typeInteger);
		tmp = cast_compat(typeInteger, typeChar, left->Valref);
		op_IR(op, tmp, right->Valref, typeInteger, &(res->Valref));
	} else if ((left->type == typeInteger) && (right->type == typeChar)) {
		res->type = binop_type_check(op, typeInteger);
		tmp = cast_compat(typeInteger, typeChar, right->Valref);
		op_IR(op, left->Valref, tmp, typeInteger, &(res->Valref));
	} else if ((left->type == typeChar) && (right->type == typeChar)) {
		res->type = binop_type_check(op, typeInteger);
		op_IR(op, left->Valref, right->Valref, typeInteger, &(res->Valref));
	} else if ((left->type == typeBoolean) && (right->type == typeBoolean)) {
		res->type = binop_type_check(op, typeBoolean);
		op_IR(op, left->Valref, right->Valref, typeBoolean, &(res->Valref));
	} else {
		my_error(ERR_LV_ERR, "Type mismatch on \"%s\" operator between %s and %s", \
				 op, verbose_type(left->type), verbose_type(right->type));
	}
}

//Type checking for an operation between operands of a given type.
Type binop_type_check(const char *op, Type t) {
	Type res = NULL;

	if (t == typeReal) {
		if ((!strcmp(op, "*")) || (!strcmp(op, "/")) || (!strcmp(op, "+")) \
				|| (!strcmp(op, "-"))) {
			res = typeReal;
		} else if ((!strcmp(op, "<")) || (!strcmp(op, ">")) || (!strcmp(op, ">=")) \
				   || (!strcmp(op, "<=")) || (!strcmp(op, "==")) \
				   || (!strcmp(op, "!="))) {
			res = typeBoolean;
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" between Reals", op);
		}
	} else if (t == typeInteger) {
		if ((!strcmp(op, "*")) || (!strcmp(op, "/")) || (!strcmp(op, "+"))  \
				|| (!strcmp(op, "-")) || (!strcmp(op, "%") || !strcmp(op, "MOD"))) {
			res = typeInteger;
		} else if ((!strcmp(op, "<")) || (!strcmp(op, ">")) || (!strcmp(op, "<="))
				   || (!strcmp(op, ">=")) || (!strcmp(op, "==")) \
				   || (!strcmp(op, "!="))) {
			res = typeBoolean;
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" between Integers", op);
		}
	} else if (t == typeBoolean) {
		if ((!strcmp(op, "==")) || (!strcmp(op, "!="))
				|| (!strcmp(op, "&&")) || (!strcmp(op,"and"))
				|| (!strcmp(op, "||")) || (!strcmp(op,"or"))) {
			res = typeBoolean;
		} else {
			my_error(ERR_LV_ERR, "Cannot perform \"%s\" between Booleans", op);
		}
	} else {
		my_error(ERR_LV_CRIT, "Internal error: invalid common operand type during binop type checking");
	}

	return res;
}

//Checks if an ast node can be used as an array index.
int array_index_check(struct ast_node *_) {
	int ret = 0;
	if  (_->type == typeChar) {
		_->value.i = (RepInteger) _->value.c;    // cast the node from char to int
	}

	if (!compat_types(typeInteger, _->type)) {
		my_error(ERR_LV_ERR, "Array index cannot be %s" , verbose_type(_->type));
		ret = 1;
	} else if (_->value.i < 0) {
		my_error(ERR_LV_ERR, "Array index cannot be negative");
		ret = 1;
	} else if (_->value.i == 0) {
		my_error(ERR_LV_ERR, "Array index cannot be zero");
		ret = 1;
	}
	return ret;
}

//Returns the number of dimensions of the type t - if not an array, returns 0.
int array_dimensions(Type t) {
	Type current = t;
	int dimensions = 0;

	while ((current->kind == TYPE_ARRAY) || (current->kind == TYPE_IARRAY)) {
		current = current->refType;
		dimensions++;
	}
	return dimensions;
}

//Calculates the type of the n-th dimension of the array.
Type n_dimension_type(Type t, int n) {
	Type current = t;
	int m = n;

	while ((m > 0) && ((current->kind == TYPE_ARRAY) || (current->kind == TYPE_IARRAY))) {
		t = t->refType;
		m--;
	}
	return t;
}

//Return true if t2 can be cast to t1.
bool compat_types(Type t1, Type t2) {
	bool res = false;
	while ((t1->kind >= TYPE_ARRAY) && (t2->kind >= TYPE_ARRAY)) {
		t1 = t1->refType;
		t2 = t2->refType;
	}
	if ((t1 == t2)
			|| ((t1 == typeInteger) && (t2 == typeChar)) \
			|| ((t1 == typeReal) && (t2 == typeInteger)) \
			|| ((t1 == typeReal) && (t2 == typeChar)) \
			|| ((t1 == typeChar) && (t2 == typeInteger))) \
		res = true;
	return res;
}


text:
import Vue from 'vue'
import Persons from '@/components/Persons'

describe('Persons.vue', () => {
    it('should render correct contents', () => {
        const Constructor = Vue.extend(Persons)
        const vm = new Constructor().$mount()
        expect(vm.$el.querySelector('.hello h1').textContent)
            .to.equal('Personregister')
    })
})

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE HTML>
<html>
<head>
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<script src="../shared-config.js"></script>
	<script id="sap-ui-bootstrap"
		src="../../../../resources/sap-ui-core.js"
		data-sap-ui-noConflict="true"
		data-sap-ui-libs="sap.m">
	</script>
	<link rel="stylesheet" href="../../../../resources/sap/ui/thirdparty/qunit.css" type="text/css" media="screen">
	<script src="../../../../resources/sap/ui/thirdparty/qunit.js"></script>
	<script src="../../../../resources/sap/ui/qunit/qunit-junit.js"></script>
	<script src="../../../../resources/sap/ui/thirdparty/sinon.js"></script>
	<!--[if IE]>
	<script src="../../../../resources/sap/ui/thirdparty/sinon-ie.js"></script>
	<![endif]-->

	<script src="../../../../resources/sap/ui/qunit/QUnitUtils.js"></script>
	<script src="../../../../resources/sap/ui/thirdparty/sinon-qunit.js"></script>

	<script>
		sinon.config.useFakeTimers = false;

		QUnit.module("Initial Check");

		QUnit.test("Initialization on desktop", function(assert) {
			var oSystem = {
				desktop: true,
				tablet: false,
				phone: false
			};

			this.stub(sap.ui.Device, "system", oSystem);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				]
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.ok(jQuery.sap.byId("master").length, "Master page should be rendered initially.");
			assert.ok(jQuery.sap.byId("detail").length, "Detail page should be rendered initially.");

			oSplitApp.destroy();
		});

		QUnit.module("Modes Check on desktop");
		QUnit.test("PopoverMode_portrait", function(assert){
			var done = assert.async();
			var oSystem = {
					desktop: true,
					tablet: false,
					phone: false
				}, oPortrait = {
					landscape: false,
					portrait: true
				};

			this.stub(sap.ui.Device, "system", oSystem);
			this.stub(sap.ui.Device, "orientation", oPortrait);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1"
					}),
					new sap.m.Page("master2",{
						title : "Master 2"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "PopoverMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.equal(oSplitApp.isMasterShown(), false, "Master area is NOT shown");

			oSplitApp._oPopOver.attachAfterOpen(function(){
				assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
				assert.ok(jQuery.sap.byId("splitapp-Popover").length, "Popover should be rendered.");
				assert.ok(oSplitApp.isMasterShown(), "Master area is shown");
				assert.equal(oSplitApp._oPopOver.getContent().length,1, "Popover content should not be empty.");
				assert.ok(jQuery.sap.byId("splitapp-MasterBtn").length, "Master Button should be rendered");
				assert.ok(jQuery.sap.byId("splitapp-MasterBtn").is(":visible"), "Master Button is shown");
				assert.ok(jQuery.sap.byId("detail").length, "Detail page should be rendered  initially.");
				assert.equal(oSplitApp.$().children().length,2, "SplitApp should only contain the detail nav container.");
				assert.equal(oSplitApp._oMasterNav.getParent().getId(), "splitapp-Popover", "Parent of Master Nav container page should be Popover.");
				oSplitApp.destroy();
				done();
			});
			oSplitApp._oPopOver.openBy(oSplitApp._oShowMasterBtn);
		});

		QUnit.test("ShowHideMode_portrait", function(assert){
			var done = assert.async();
			var oSystem = {
					desktop: true,
					tablet: false,
					phone: false
				}, oPortrait = {
					landscape: false,
					portrait: true
				};

			this.stub(sap.ui.Device, "system", oSystem);
			this.stub(sap.ui.Device, "orientation", oPortrait);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "ShowHideMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.equal(oSplitApp._oPopOver.getContent().length, 0, "Popover content should be empty.");
			assert.equal(oSplitApp._oMasterNav.getParent().getId(), "splitapp", "Parent of Master page should be SpltApp.");
			assert.ok(jQuery.sap.byId("detail").length, "Detail Nav Container should be rendered initially.");
			assert.ok(jQuery.sap.byId("master").length, "Master Nav Container should be rendered initially.");
			assert.equal(oSplitApp.isMasterShown(), false, "Master area is NOT shown");
			assert.ok(jQuery.sap.byId("splitapp-MasterBtn").length, "Master Button should be rendered");
			assert.ok(!jQuery.sap.byId("splitapp-MasterBtn").is(":hidden"), "Master Button is shown");
			assert.equal(oSplitApp.$().children().length, 3, "Splitapp should render both master and detail.");

			oSplitApp.showMaster();
			setTimeout(function(){
				assert.equal(oSplitApp.isMasterShown(), true, "Master area is shown");
				oSplitApp.destroy();
				done();
			}, 400);
		});

		QUnit.test("StretchCompressMode_portrait", function(assert){
			var oSystem = {
					desktop: true,
					tablet: false,
					phone: false
				}, oPortrait = {
					landscape: false,
					portrait: true
				};

			this.stub(sap.ui.Device, "system", oSystem);
			this.stub(sap.ui.Device, "orientation", oPortrait);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "StretchCompressMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.equal(oSplitApp._oPopOver.getContent().length, 0, "Popover content should be empty.");
			assert.ok(jQuery.sap.byId("detail").length, "Master Nav Container should be rendered initially.");
			//assert.equal(jQuery("#splitapp-MasterBtn").css("display"), "none", "Master Button is not shown");	           TODO
			assert.equal(oSplitApp.$().children().length, 3, "Master page should be rendered initially.");
			assert.equal(oSplitApp.isMasterShown(), true, "Master area is shown");
			assert.equal(jQuery.sap.byId("splitapp-Master").outerWidth(), 320, "Master width should be 320px.");
			oSplitApp.destroy();
		});

		QUnit.test("PopoverMode_landscape", function(assert){
			var oSystem = {
					desktop: true,
					tablet: false,
					phone: false
				}, oLandscape = {
					landscape: true,
					portrait: false
				};

			this.stub(sap.ui.Device, "system", oSystem);
			this.stub(sap.ui.Device, "orientation", oLandscape);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "PopoverMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.equal(oSplitApp._oPopOver.getContent().length, 0, "Popover content should be empty.");
			assert.ok(jQuery.sap.byId("detail").length, "Detail Nav Container should be rendered");
			assert.ok(jQuery.sap.byId("master").length, "Master Nav Container page should be rendered");
			assert.equal(oSplitApp.$().children().length, 3, "Master page should be rendered initially.");
			assert.equal(oSplitApp.isMasterShown(), true, "Master area is shown");
			assert.equal(oSplitApp.$("Master").outerWidth(),320, "Master width should be 320px.");

			oSplitApp.destroy();
		});

		QUnit.test("ShowHideMode_landscape", function(assert){
			var oSystem = {
					desktop: true,
					tablet: false,
					phone: false
				}, oLandscape = {
					landscape: true,
					portrait: false
				};

			this.stub(sap.ui.Device, "system", oSystem);
			this.stub(sap.ui.Device, "orientation", oLandscape);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "ShowHideMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.equal(oSplitApp._oPopOver.getContent().length, 0, "Popover content should be empty.");
			assert.ok(jQuery.sap.byId("detail").length, "Detail Nav Container should be rendered");
			assert.ok(jQuery.sap.byId("master").length, "Master Nav Container should be rendered");
			assert.equal(oSplitApp.$().children().length, 3 ,"Master page should be rendered initially.");
			assert.equal(oSplitApp.isMasterShown(), true, "Master area is shown");
			assert.equal(oSplitApp.$("Master").outerWidth(), 320, "Master width should be 320px.");

			oSplitApp.destroy();
		});

		QUnit.test("StretchCompressMode_landscape", function(assert){
			var oSystem = {
					desktop: true,
					tablet: false,
					phone: false
				}, oLandscape = {
					landscape: true,
					portrait: false
				};

			this.stub(sap.ui.Device, "system", oSystem);
			this.stub(sap.ui.Device, "orientation", oLandscape);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "StretchCompressMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.equal(oSplitApp._oPopOver.getContent().length, 0, "Popover content should be empty.");
			assert.ok(jQuery.sap.byId("detail").length, "Detail Nav Container should be rendered");
			assert.ok(jQuery.sap.byId("master").length, "Master Nav Container should be rendered");
			assert.equal(oSplitApp.$().children().length, 3, "Master page should be rendered initially.");
			assert.equal(oSplitApp.isMasterShown(), true, "Master area is shown");

			assert.ok(!jQuery.sap.byId("splitapp-Master").is(":hidden"),"Master should be visible.");
			assert.equal(jQuery.sap.byId("splitapp-Master").outerWidth(),320, "Master width should be 320px.");
			oSplitApp.destroy();
		});

		QUnit.test("HideMode", function(assert){
			var oSystem = {
				desktop: true,
				tablet: false,
				phone: false
			};

			this.stub(sap.ui.Device, "system", oSystem);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "HideMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.equal(oSplitApp._oPopOver.getContent().length, 0, "Popover content should be empty.");
			assert.ok(jQuery.sap.byId("detail").length, "Detail Nav Container should be rendered initially.");
			assert.ok(jQuery.sap.byId("splitapp-MasterBtn").length, "Master Button should be rendered");
			assert.equal(oSplitApp.$().children().length, 3, "Master page should be rendered initially.");
			assert.equal(oSplitApp.isMasterShown(), false, "Master area is NOT shown");
			assert.ok(jQuery.sap.byId("splitapp-Master").position().left <= -320, "Master should be hidden.");
			oSplitApp.destroy();
		});

		QUnit.module("Public Methods");
		QUnit.test("ShowMaster", function(assert){
			var done = assert.async();
			var oSystem = {
					desktop: true,
					tablet: false,
					phone: false
				}, oPortrait = {
					landscape: false,
					portrait: true
				};

			this.stub(sap.ui.Device, "system", oSystem);
			this.stub(sap.ui.Device, "orientation", oPortrait);

			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "ShowHideMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			oSplitApp.showMaster();

			setTimeout(function(){
				assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
				assert.equal(oSplitApp._oPopOver.getContent().length, 0, "Popover content should be empty.");
				assert.ok(jQuery.sap.byId("detail").length, "Detail Nav Container should be rendered");
				assert.ok(jQuery.sap.byId("master").length, "Master Nav Container should be rendered");
				assert.equal(oSplitApp.$().children().length, 3, "Master page should be rendered initially.");

				assert.ok(!jQuery("#splitapp-Master").is(":hidden"),"Master should not be hidden.");
				assert.equal(jQuery("#splitapp-Master").outerWidth(), 320, "Master width should be 320px.");
				oSplitApp.destroy();
				done();
			}, 500);
		});

		QUnit.test("Initialization on phone", function(assert) {
			var oSystem = {
				desktop: false,
				tablet: false,
				phone: true
			};
			this.stub(sap.ui.Device, "system", oSystem);
			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				],
				mode: "ShowHideMode"
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			assert.ok(jQuery.sap.byId("splitapp").length, "SplitApp is rendered in the beginning.");
			assert.ok(jQuery.sap.byId("master").length, "Master Nav Container should be rendered initially.");
			assert.equal(jQuery.sap.byId("detail").length , 0, "Detail Nav Container should not be rendered.");
			assert.equal(jQuery.sap.byId("splitapp-MasterBtn").length, 0, "Master Button should not be rendered");
			oSplitApp.destroy();
		});

		// Tests for all modes
		QUnit.module("Master / Detail page aggregation");
		QUnit.test("Master / Detail page aggregation returns the right pages in the right order", function(assert) {
			var oMasterPage = new sap.m.Page("master",{
				title : "Master 1",
				content: [new sap.m.Button("Button", {text: "That is a Button"})]
			});
			var oMasterPage2 = new sap.m.Page("master2",{
				title : "Master 1"
			});
			var oDetailPage = new sap.m.Page("detail",{
				title : "Detail 1"
			});
			var oDetailPage2 = new sap.m.Page("detail2",{
				title : "Detail 2"
			});
			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					oMasterPage, oMasterPage2
				],
				detailPages: [
					oDetailPage, oDetailPage2
				]
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			var oSpyIndexOfPage = this.spy(oSplitApp._oMasterNav, "indexOfPage");

			var aMaster = oSplitApp.getMasterPages();
			var aDetail = oSplitApp.getDetailPages();
			assert.equal(aMaster.length, 2, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 2, "Detail page aggregation contains the right number of pages");

			assert.equal(oSplitApp.indexOfMasterPage(oMasterPage), 0, "Master page is in the right aggregation and order");
			assert.equal(oSplitApp.indexOfMasterPage(oMasterPage2), 1, "Master page 2 is in the right aggregation and order");
			assert.equal(oSplitApp.indexOfDetailPage(oDetailPage), 0, "Detail page is in the right aggregation and order");
			assert.equal(oSplitApp.indexOfDetailPage(oDetailPage2), 1, "Detail page 2 is in the right aggregation and order");

			var oSpyIndexOfMasterPage = this.spy(oSplitApp, "_indexOfMasterPage");
			assert.equal(oSplitApp.indexOfAggregation("masterPages", oMasterPage), 0, "Master page is in the right aggregation and order");

			assert.ok(!oSpyIndexOfPage.called, "Right delegate method was called");
			assert.ok(oSpyIndexOfMasterPage.called, "Right delegate method was called");
			oSplitApp.destroy();
		});

		QUnit.test("Adding / Removing Pages to/from Master / Detail", function(assert) {
			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				]
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			var oNewMasterPage = new sap.m.Page("newMasterPage1",{
				title : "Master 1"
			});

			var oSpyInsertPage = this.spy(oSplitApp._oMasterNav, "insertPage");
			var oSpyRemovePage = this.spy(oSplitApp._oMasterNav, "removePage");

			oSplitApp.addMasterPage(oNewMasterPage);

			var oNewDetailPage = new sap.m.Page("newDetailPage1",{
				title : "Detail 1"
			});

			oSplitApp.addDetailPage(oNewDetailPage);

			var aMaster = oSplitApp.getMasterPages();
			var aDetail = oSplitApp.getDetailPages();
			assert.equal(aMaster.length, 3, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 3, "Detail page aggregation contains the right number of pages");

			oSplitApp.removeMasterPage(oNewMasterPage);
			oSplitApp.removeDetailPage(oNewDetailPage);

			assert.equal(aMaster.length, 2, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 2, "Detail page aggregation contains the right number of pages");

			oSplitApp.addMasterPage(oNewMasterPage);
			oSplitApp.addDetailPage(oNewDetailPage);
			assert.equal(aMaster.length, 3, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 3, "Detail page aggregation contains the right number of pages");
			oNewDetailPage.destroy();
			oNewMasterPage.destroy();
			assert.equal(aMaster.length, 2, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 2, "Detail page aggregation contains the right number of pages");

			assert.ok(oSpyInsertPage.called, "Right delegate method was called");
			assert.ok(oSpyRemovePage.called, "Right delegate method was called");

			oSplitApp.destroy();
		});

		QUnit.test("Moving Page from Master to Detail", function(assert) {
			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				]
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			var aMaster = oSplitApp.getMasterPages();
			var aDetail = oSplitApp.getDetailPages();

			var oMovePage = new sap.m.Page("movePagePage1",{
				title : "Detail 1"
			});

			oSplitApp.addMasterPage(oMovePage);
			assert.equal(aMaster.length, 3, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 2, "Detail page aggregation contains the right number of pages");
			oSplitApp.addDetailPage(oMovePage);
			assert.equal(aMaster.length, 2, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 3, "Detail page aggregation contains the right number of pages");
			oSplitApp.removeDetailPage(oMovePage);
			assert.equal(aMaster.length, 2, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 2, "Detail page aggregation contains the right number of pages");

			oMovePage.destroy();
			oSplitApp.destroy();
		});

		QUnit.test("Insert Page", function(assert) {
			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				]
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			var aMaster = oSplitApp.getMasterPages();
			var aDetail = oSplitApp.getDetailPages();

			var oSpyInsertPage = this.spy(oSplitApp._oMasterNav, "insertPage");

			var oInsertPage = new sap.m.Page("insertPagePage",{
				title : "Detail 1"
			});

			oSplitApp.insertMasterPage(oInsertPage, 1);
			assert.equal(aMaster.length, 3, "Master page aggregation contains the right number of pages");
			assert.equal(oSplitApp.indexOfMasterPage(oInsertPage), 1, "Master page is in the right position");
			oInsertPage.destroy();

			// Check against native implementation
			var oNavContainer = new sap.m.NavContainer("navcontainer", {});
			var oInsertPage1 = new sap.m.Page("insertPagePage1",{
				title : "Detail 1"
			});
			var oInsertPage2 = new sap.m.Page("insertPagePage2",{
				title : "Detail 1"
			});
			var oInsertPage3 = new sap.m.Page("insertPagePage3",{
				title : "Detail 1"
			});
			oNavContainer.addPage(oInsertPage1);
			oNavContainer.addPage(oInsertPage2);
			oNavContainer.insertPage(oInsertPage3, 1);
			assert.equal(oNavContainer.indexOfPage(oInsertPage3), 1, "Validation against native Implementation: Page is in the right position");

			assert.ok(oSpyInsertPage.called, "Right delegate method was called");

			oNavContainer.destroy();
			oSplitApp.destroy();
		});

		QUnit.test("Remove all pages", function(assert) {
			var oSplitApp = new sap.m.SplitApp("splitapp", {
				masterPages: [
					new sap.m.Page("master",{
						title : "Master 1",
						content: [new sap.m.Button("Button", {text: "That is a Button"})]
					}),
					new sap.m.Page("master2",{
						title : "Master 1"
					})
				],
				detailPages: [
					new sap.m.Page("detail",{
						title : "Detail 1"
					}),
					new sap.m.Page("detail2",{
						title : "Detail 2"
					})
				]
			});
			oSplitApp.placeAt("content");
			sap.ui.getCore().applyChanges();

			var oSpyRemoveAllPages = this.spy(oSplitApp._oMasterNav, "removeAllPages");

			oSplitApp.removeAllMasterPages();
			oSplitApp.removeAllDetailPages();

			var aMaster = oSplitApp.getMasterPages();
			var aDetail = oSplitApp.getDetailPages();
			assert.equal(aMaster.length, 0, "Master page aggregation contains the right number of pages");
			assert.equal(aDetail.length, 0, "Detail page aggregation contains the right number of pages");

			assert.ok(oSpyRemoveAllPages.called, "Right delegate method was called");

			oSplitApp.destroy();
		});

		QUnit.test("keyboard handling with showMasterButton", function(assert){
			var done = assert.async();
			var oSystem = {
					desktop: true,
					phone: false,
					tablet: false
				};

			this.stub(sap.ui.Device, "system", oSystem);

			this.stub(jQuery.device, "is", oSystem);

			var	oSplitApp1 = new sap.m.SplitApp({
				mode: sap.m.SplitAppMode.HideMode
			});

			var page = new sap.m.Page("master_1");
			var page2 = new sap.m.Page("detail_1");
			oSplitApp1.addMasterPage(page).addDetailPage(page2);

			oSplitApp1.placeAt("content");
			sap.ui.getCore().applyChanges();

			var oMasterButton = oSplitApp1._oShowMasterBtn;
			assert.ok(oMasterButton.getDomRef(), "Master Button is rendered");
			assert.ok(oMasterButton.$().css("display") !== "none", "Master Button should be shown");
			oMasterButton.$().focus();
			sap.ui.test.qunit.triggerKeydown(oMasterButton.getDomRef(), jQuery.sap.KeyCodes.ENTER);
			sap.ui.test.qunit.triggerKeyup(oMasterButton.getDomRef(), jQuery.sap.KeyCodes.ENTER);
			setTimeout(function(){
				assert.ok(oSplitApp1.isMasterShown(), "Master should be opened");
				oSplitApp1.destroy();
				done();
			}, 500);
		});
	</script>
	</head>
	<body id="body" class="sapUiBody">
		<h1 id="qunit-header">QUnit Page for sap.m.SplitApp</h1>
		<h2 id="qunit-banner"></h2>
		<h2 id="qunit-userAgent"></h2>
		<ol id="qunit-tests"></ol>
		<div id="content"></div>
	</body>
</html>


text:
"""
Kay runserver management commands.

:Copyright: (c) 2009 Accense Technology, Inc. All rights reserved.
:license: BSD, see LICENSE for more details.
"""

import os
import sys

from kay.misc import get_datastore_paths
from kay.management.utils import print_status

def args_have_option(args, option):
  for arg in args:
    if arg.startswith(option):
      return True
  return False

def runserver_passthru_argv():
  """
  Execute dev_appserver with appropriate parameters. For more details,
  please invoke 'python manage.py runserver --help'.
  """
  from google.appengine.tools import dev_appserver_main
  progname = "manage.py runserver"
  args = []
  args.extend(sys.argv[2:])

  p = get_datastore_paths()
  if not args_have_option(args, "--datastore_path"):
    args.extend(["--datastore_path", p[0]])
  if not args_have_option(args, "--history_path"):
    args.extend(["--history_path", p[1]])
  # Append the current working directory to the arguments.
  if "-h" in args or "--help" in args:
    render_dict = dev_appserver_main.DEFAULT_ARGS.copy()
    render_dict['script'] = "manage.py runserver"
    print_status(dev_appserver_main.__doc__ % render_dict)
    sys.stdout.flush()
    sys.exit(0)
  dev_appserver_main.main([progname] + args + [os.getcwdu()])

runserver_passthru_argv.passthru = True


text:
namespace SharpE.Templats
{
  enum TemplateCommandType
  {
    Undefined,
    Copy,
    CreateFolder,
    Replace,
    Insert,
    InjectJson
  }
}


text:
layout: default
title: active_callback
published: false
---

You can use the `active_callback` argument to define if you want to hide or display a control under conditions.

The default WordPress Customizer implementation for `active_callback` allows you to define a callable function or method (see the [Customizer API Handbook](https://developer.wordpress.org/themes/advanced-topics/customizer-api/#contextual-controls-sections-and-panels) for details).

Kirki extends the `active_callback` argument to allow defined field dependencies:

```php
<?php
'active_callback'    => array(
	array(
		'setting'  => 'checkbox_demo',
		'operator' => '==',
		'value'    => true,
	),
),
?>
```
It is formatted as an array of arrays so you can add multiple dependencies.

* `setting`: you can use the `settings` argument of the controller-field.
* `operator`: you can use any of the following:
  * `===` : uses PHP's `===` to evaluate the value
  * `==`, `=`, `equal`, `equals` : uses PHP's `==` to evaluate the value
  * `!==` : uses PHP's `!==` to evaluate the value
  * `!=`, `not equal` : uses PHP's `!==` to evaluate the value
  * `>=`, `greater or equal`, `equal or greater` : uses PHP's `>=` to evaluate the value
  * `<=`, `smaller or equal`, `equal or smaller`: uses PHP's `<=` to evaluate the value
  * `>`, `greater` : uses PHP's `>` to evaluate the value
  * `<`, `smaller` : uses PHP's `<` to evaluate the value
  * `contains`, `in` : If the context is an array then we'll check if the value defined exists in the array (using PHP's [`in_array()`](http://php.net/manual/en/function.in-array.php) function. If on the other hand the context is a string then we'll check if the string contains the value defined using PHP's [`strpos()`](http://php.net/manual/en/function.strpos.php) and checking not the position of the string but whether the result returns `false` or not (using `===` for safety).
* `value`: the value of the controller-field against which all comparisons and checks will be performed to determin if the field should be visible or not.

In the example below we're first creating a config, then a section, and finally we add 3 fields to our customizer: a checkbox, a radio and finally a text control.

The text control will **only** be shown if the value of the checkbox is equal to 1 **and** the value of the radio control is not equal to `option-1`.

```php
<?php
Kirki::add_config( 'my_config' );

Kirki::add_section( 'my_section', array(
    'title'          => __( 'My Section' ),
    'priority'       => 10,
) );

Kirki::add_field( 'my_config', array(
	'type'      => 'checkbox',
	'settings'  => 'my_checkbox',
	'label'     => __( 'My Checkbox', 'my_textdomain' ),
	'section'   => 'my_section',
	'default'   => 0,
	'priority'  => 10,
) );

Kirki::add_field( 'my_config', array(
	'type'      => 'radio',
	'settings'  => 'my_radio',
	'label'     => __( 'My Radio', 'my_textdomain' ),
	'section'   => 'my_section',
	'default'   => 'option-1',
	'priority'  => 20,
	'choices'   => array(
		'option-1' => __( 'Option 1', 'my_textdomain' ),
		'option-2' => __( 'Option 2', 'my_textdomain' ),
		'option-3' => __( 'Option 3', 'my_textdomain' )
	)
) );

Kirki::add_field( 'my_config', array(
	'type'      => 'text',
	'settings'  => 'my_setting',
	'label'     => __( 'Text Color', 'my_textdomain' ),
	'section'   => 'my_section',
	'default'   => __( 'my default text here', 'my_textdomain' ),
	'priority'  => 30,
	'active_callback'  => array(
		array(
			'setting'  => 'my_checkbox',
			'operator' => '==',
			'value'    => 1,
		),
		array(
			'setting'  => 'my_radio',
			'operator' => '!=',
			'value'    => 'option-1',
		),
	)
) );
?>
```


text:
package dk.brics.tajs.lattice;

import dk.brics.tajs.flowgraph.AbstractNode;
import dk.brics.tajs.util.Collectors;

import java.util.Map;

import static dk.brics.tajs.util.Collections.newMap;

/**
 * Local must-reaching definitions.
 *
 * The must-reaching definition of a register is the node where the register must have obtained its value.
 * This information is used for filtering at explicit and implicit branches.
 */
public class MustReachingDefs { // TODO: use copy-on-write?

    /**
     * Map from register to the node that must have defined the value of the register, or absent if no such node.
     */
    private Map<Integer, AbstractNode> registerDefs;

    /**
     * Constructs a new empty MustReachingDefs.
     */
    public MustReachingDefs() {
        registerDefs = newMap();
    }

    /**
     * Constructs a new MustReachingDefs as a copy of the given one.
     */
    public MustReachingDefs(MustReachingDefs old) {
        registerDefs = newMap(old.registerDefs);
    }

    /**
     * Empties this MustReachingDefs.
     */
    public void setToBottom() {
        registerDefs.clear();
    }

    /**
     * Empties this MustReachingDefs for the given register.
     */
    public void setToBottom(int reg) {
        registerDefs.remove(reg);
    }

    /**
     * Adds a must-reaching definition for a register.
     */
    public void addReachingDef(int reg, AbstractNode node) {
        discardOldEntries();
        registerDefs.put(reg, node);
    }

    /**
     * Discard old entries if too many.
     */
    private void discardOldEntries() {
        int LIMIT = 50;
        if (registerDefs.size() > LIMIT) {
            registerDefs = registerDefs.entrySet().stream().sorted((e1, e2) -> e2.getValue().getIndex() - e1.getValue().getIndex()).limit(LIMIT / 2).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        }
    }

    /**
     * Returns the must-reaching definition for the given register, or null if not available.
     */
    public AbstractNode getReachingDef(int reg) {
        return registerDefs.get(reg);
    }

    /**
     * Propagates the given MustReachingDefs into this one.
     * @return if this MustReachingDefs changed
     */
    public boolean propagate(MustReachingDefs must_reaching_defs) {
        Map<Integer, AbstractNode> newRegisterDefs = newMap();
        registerDefs.forEach((reg, node) -> {
            if (node == must_reaching_defs.getReachingDef(reg))
                newRegisterDefs.put(reg, node);
        });
        boolean changed = newRegisterDefs.size() != registerDefs.size();
        registerDefs = newRegisterDefs;
        return changed;
    }

    @Override
    public String toString() {
        StringBuilder b = new StringBuilder();
        registerDefs.forEach((reg, node) -> b.append("\n    v").append(reg).append(": node ").append(node.getIndex()).append(" (").append(node.getSourceLocation()).append(')'));
        return b.toString();
    }
}


text:
"""
This file is part of pyCMBS.
(c) 2012- Alexander Loew
For COPYING and LICENSE details, please refer to the LICENSE file
"""

import unittest
import os
import pycmbs.benchmarking.utils as utils

class TestUtils(unittest.TestCase):

    def setUp(self):
        # setup environment variables
        os.environ['SEP'] = os.getcwd() + os.sep + 'SEP'
        os.environ['CDOTEMPDIR'] = os.getcwd() + os.sep + 'CDOTEMPDIR'
        if not os.path.exists(os.environ['SEP']):
            os.makedirs(os.environ['SEP'])
        if not os.path.exists(os.environ['CDOTEMPDIR']):
            os.makedirs(os.environ['CDOTEMPDIR'])

    def tearDown(self):
        # remove temporary dirs
        if os.path.exists(os.getcwd() + os.sep + 'SEP'):
            cmd = 'rm -rf ' + os.getcwd() + os.sep + 'SEP'
            os.system(cmd)
        if os.path.exists(os.getcwd() + os.sep + 'CDOTEMPDIR'):
            cmd = 'rm -rf ' + os.getcwd() + os.sep + 'CDOTEMPDIR'
            os.system(cmd)

    def test_get_data_pool_OK(self):
        os.environ['SEP'] = os.getcwd()
        p = utils.get_data_pool_directory()
        self.assertEqual(p, os.getcwd())

    def test_PoolDirectory_SetToCwd(self):
        os.environ.pop('SEP')
        local_dir = os.getcwd() + os.sep
        pool_dir = utils.get_data_pool_directory()
        self.assertEqual(pool_dir, local_dir)

    @unittest.skip('skipping as it\'s hard to emulate a non existing root path')
    def test_get_data_pool_Default(self):
        if 'SEP' in os.environ.keys():
            xx = os.environ.pop('SEP')
        p = utils.get_data_pool_directory()
        self.assertEqual(p, '/pool/SEP/')
        os.environ.update({'SEP': xx})

    def test_get_data_pool_MultipleDirs(self):
        r = os.environ['SEP']
        os.environ.update({'SEP' : '/some/first/path:' + r })
        p = utils.get_data_pool_directory()
        self.assertEqual(p, r)
        os.environ.update({'SEP': r})

    def test_get_data_pool_MultipleDirs2(self):
        r = os.environ['SEP']
        os.environ.update({'SEP' : r + ':/some/second/dir' })
        p = utils.get_data_pool_directory()
        self.assertEqual(p, r)
        os.environ.update({'SEP': r})

    def test_cdo_tempdir_fromENV(self):
        d = '/some/directory/path'
        os.environ.update({'CDOTEMPDIR': d})
        r = utils.get_temporary_directory()
        self.assertEqual(r, d + '/')

    def test_cdo_tempdir_fromENV1(self):
        d = '/some/directory/path/'
        os.environ.update({'CDOTEMPDIR': d})
        r = utils.get_temporary_directory()
        self.assertEqual(r, d)

    def test_cdo_tempdir_DefaultNoEnv(self):
        if 'CDOTEMPDIR' in os.environ.keys():
            d = os.environ.pop('CDOTEMPDIR')
        r = utils.get_temporary_directory()
        self.assertEqual(r, './')

    @unittest.skip('TODO: acquire files using wget script!')
    def test_get_generic_landseamask_DEFAULT(self):
        #XXX TODO analyze also correctness of results
        ls = utils.get_generic_landseamask(False)
        ls = utils.get_generic_landseamask(True, area='ocean')
        ls = utils.get_generic_landseamask(True, area='global')
        ls = utils.get_generic_landseamask(False, mask_antarctica=False)
        fname = ['land_sea_fractions_remapnn_t63grid.nc', 'land_sea_fractions_remapnn_t63grid_cell_area.nc']
        self.assertTrue(os.path.exists(fname[0]))
        for f in fname:
            if os.path.exists(f):
                os.remove(f)

if __name__ == "__main__":
    unittest.main()


text:
// Generated by the protocol buffer compiler.  DO NOT EDIT!
// source: google/cloud/speech/v1p1beta1/cloud_speech.proto

package com.google.cloud.speech.v1p1beta1;

public interface RecognitionAudioOrBuilder
    extends
    // @@protoc_insertion_point(interface_extends:google.cloud.speech.v1p1beta1.RecognitionAudio)
    com.google.protobuf.MessageOrBuilder {

  /**
   *
   *
   *

   * The audio data bytes encoded as specified in
   * `RecognitionConfig`. Note: as with all bytes fields, proto buffers use a
   * pure binary representation, whereas JSON representations use base64.
   *

   *
   * bytes content = 1;
   *
   * @return Whether the content field is set.
   */
  boolean hasContent();
  /**
   *
   *
   *

   * The audio data bytes encoded as specified in
   * `RecognitionConfig`. Note: as with all bytes fields, proto buffers use a
   * pure binary representation, whereas JSON representations use base64.
   *

   *
   * bytes content = 1;
   *
   * @return The content.
   */
  com.google.protobuf.ByteString getContent();

  /**
   *
   *
   *

   * URI that points to a file that contains audio data bytes as specified in
   * `RecognitionConfig`. The file must not be compressed (for example, gzip).
   * Currently, only Google Cloud Storage URIs are
   * supported, which must be specified in the following format:
   * `gs://bucket_name/object_name` (other URI formats return
   * [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]). For more information, see
   * [Request URIs](https://cloud.google.com/storage/docs/reference-uris).
   *

   *
   * string uri = 2;
   *
   * @return Whether the uri field is set.
   */
  boolean hasUri();
  /**
   *
   *
   *

   * URI that points to a file that contains audio data bytes as specified in
   * `RecognitionConfig`. The file must not be compressed (for example, gzip).
   * Currently, only Google Cloud Storage URIs are
   * supported, which must be specified in the following format:
   * `gs://bucket_name/object_name` (other URI formats return
   * [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]). For more information, see
   * [Request URIs](https://cloud.google.com/storage/docs/reference-uris).
   *

   *
   * string uri = 2;
   *
   * @return The uri.
   */
  java.lang.String getUri();
  /**
   *
   *
   *

   * URI that points to a file that contains audio data bytes as specified in
   * `RecognitionConfig`. The file must not be compressed (for example, gzip).
   * Currently, only Google Cloud Storage URIs are
   * supported, which must be specified in the following format:
   * `gs://bucket_name/object_name` (other URI formats return
   * [google.rpc.Code.INVALID_ARGUMENT][google.rpc.Code.INVALID_ARGUMENT]). For more information, see
   * [Request URIs](https://cloud.google.com/storage/docs/reference-uris).
   *

   *
   * string uri = 2;
   *
   * @return The bytes for uri.
   */
  com.google.protobuf.ByteString getUriBytes();

  public com.google.cloud.speech.v1p1beta1.RecognitionAudio.AudioSourceCase getAudioSourceCase();
}


text:
Dependencies

	The following example is using Material icons, so make sure to load the icons library into the <head> section of your page before using the example.

{% markdown %}
```html
<!-- Material Design Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
```
{% endmarkdown %}


text:
package com.amazonaws.services.cloudtrail.model.transform;

import java.util.List;
import javax.annotation.Generated;

import com.amazonaws.SdkClientException;
import com.amazonaws.services.cloudtrail.model.*;

import com.amazonaws.protocol.*;
import com.amazonaws.annotation.SdkInternalApi;

/**
 * PutEventSelectorsRequestMarshaller
 */
@Generated("com.amazonaws:aws-java-sdk-code-generator")
@SdkInternalApi
public class PutEventSelectorsRequestMarshaller {

    private static final MarshallingInfo<String> TRAILNAME_BINDING = MarshallingInfo.builder(MarshallingType.STRING).marshallLocation(MarshallLocation.PAYLOAD)
            .marshallLocationName("TrailName").build();
    private static final MarshallingInfo<List> EVENTSELECTORS_BINDING = MarshallingInfo.builder(MarshallingType.LIST)
            .marshallLocation(MarshallLocation.PAYLOAD).marshallLocationName("EventSelectors").build();

    private static final PutEventSelectorsRequestMarshaller instance = new PutEventSelectorsRequestMarshaller();

    public static PutEventSelectorsRequestMarshaller getInstance() {
        return instance;
    }

    /**
     * Marshall the given parameter object.
     */
    public void marshall(PutEventSelectorsRequest putEventSelectorsRequest, ProtocolMarshaller protocolMarshaller) {

        if (putEventSelectorsRequest == null) {
            throw new SdkClientException("Invalid argument passed to marshall(...)");
        }

        try {
            protocolMarshaller.marshall(putEventSelectorsRequest.getTrailName(), TRAILNAME_BINDING);
            protocolMarshaller.marshall(putEventSelectorsRequest.getEventSelectors(), EVENTSELECTORS_BINDING);
        } catch (Exception e) {
            throw new SdkClientException("Unable to marshall request to JSON: " + e.getMessage(), e);
        }
    }

}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>Source code</title>
<link rel="stylesheet" type="text/css" href="../../../stylesheet.css" title="Style">

001package squidpony.squidmath;
002
003import java.io.Serializable;
004import java.util.ArrayList;
005import java.util.Collection;
006import java.util.Iterator;
007
008/**
009 * Meant to take a fixed-size set of items and produce a shuffled stream of them such that an element is never chosen in
010 * quick succession; that is, there should always be a gap between the same item's occurrences. This is an Iterable of
011 * T, not a Collection, because it can iterate without stopping, infinitely, unless you break out of a foreach loop that
012 * iterates through one of these, or call the iterator's next() method only a limited number of times. Collections have
013 * a size that can be checked, but Iterables can be infinite (and in this case, this one is).
014 * Created by Tommy Ettinger on 5/21/2016.
015 * @param <T> the type of items to iterate over; ideally, the items are unique
016 */
017public class GapShuffler<T> implements Iterator<T>, Iterable<T>, Serializable {
018    private static final long serialVersionUID = 1277543974688106290L;
019    public RNG rng;
020    private ArrayList<T> elements;
021    private int size, index;
022    private int[][] indexSections;
023    private GapShuffler() {}
024
025    /**
026     * Constructor that takes any Collection of T, shuffles it with an unseeded RNG, and can then iterate infinitely
027     * through mostly-random shuffles of the given collection. These shuffles are spaced so that a single element should
028     * always have a large amount of "gap" in order between one appearance and the next. It helps to keep the appearance
029     * of a gap if every item in elements is unique, but that is not necessary and does not affect how this works.
030     * @param elements a Collection of T that will not be modified
031     */
032    public GapShuffler(Collection<T> elements)
033    {
034        rng = new RNG(new LongPeriodRNG());
035        this.elements = rng.shuffle(elements);
036        size = this.elements.size();
037        double sz2 = size;
038        index = 0;
039        int portionSize = Math.min(20, Math.max(1, size / 2));
040        int minSection = Math.min(5, size / 2 + 1);
041        while (size % portionSize < minSection && portionSize > 2)
042            portionSize--;
043        indexSections = new int[(int)Math.ceil(sz2 / portionSize)][];
044        for (int i = 0; i < indexSections.length - 1; i++) {
045            indexSections[i] = PermutationGenerator.decodePermutation(
046                    rng.nextLong(PermutationGenerator.getTotalPermutations(portionSize)), portionSize, i * portionSize);
047            sz2 -= portionSize;
048        }
049        indexSections[indexSections.length - 1] = PermutationGenerator.decodePermutation(
050                rng.nextLong(PermutationGenerator.getTotalPermutations((int)sz2)),
051                (int)sz2, (indexSections.length - 1) * portionSize);
052    }
053
054    /**
055     * Constructor that takes any Collection of T, shuffles it with the given RNG, and can then iterate infinitely
056     * through mostly-random shuffles of the given collection. These shuffles are spaced so that a single element should
057     * always have a large amount of "gap" in order between one appearance and the next. It helps to keep the appearance
058     * of a gap if every item in elements is unique, but that is not necessary and does not affect how this works. The
059     * rng parameter is copied so externally using it won't change the order this produces its values; the rng field is
060     * used whenever the iterator needs to re-shuffle the internal ordering of elements. I suggest that the RNG should
061     * use LongPeriodRNG as its RandomnessSource, since it is in general a good choice for shuffling, but since this
062     * class mostly delegates its unique-shuffling code to PermutationGenerator and looks up at most 20 elements'
063     * permutation at once (allowing it to use a single random long to generate the permutation), there probably won't
064     * be problems if you use any other RandomnessSource.
065     * @param elements a Collection of T that will not be modified
066     * @param rng an RNG that can be pre-seeded; will be copied and not used directly
067     */
068    public GapShuffler(Collection<T> elements, RNG rng)
069    {
070        this.rng = rng.copy();
071        this.elements = rng.shuffle(elements);
072        size = this.elements.size();
073        double sz2 = size;
074        index = 0;
075        int portionSize = Math.min(20, Math.max(1, size / 2));
076        int minSection = Math.min(5, size / 2 + 1);
077        while (size % portionSize < minSection && portionSize > 2)
078            portionSize--;
079        indexSections = new int[(int)Math.ceil(sz2 / portionSize)][];
080        for (int i = 0; i < indexSections.length - 1; i++) {
081            indexSections[i] = PermutationGenerator.decodePermutation(
082                    rng.nextLong(PermutationGenerator.getTotalPermutations(portionSize)), portionSize, i * portionSize);
083            sz2 -= portionSize;
084        }
085        indexSections[indexSections.length - 1] = PermutationGenerator.decodePermutation(
086                rng.nextLong(PermutationGenerator.getTotalPermutations((int)sz2)),
087                (int)sz2, (indexSections.length - 1) * portionSize);
088    }
089
090    /**
091     * Gets the next element of the infinite sequence of T this shuffles through. This class can be used as an
092     * Iterator or Iterable of type T.
093     * @return the next element in the infinite sequence
094     */
095    public T next() {
096        if(index >= size)
097        {
098            index = 0;
099            int build = 0, inner, rotated;
100            for (int i = 0; i < indexSections.length; i++) {
101                if(indexSections.length <= 2)
102                    rotated = (indexSections.length + 2 - i) % indexSections.length;
103                else
104                    rotated = (indexSections.length + 1 - i) % indexSections.length;
105                inner = indexSections[rotated].length;
106                indexSections[rotated] =
107                        PermutationGenerator.decodePermutation(
108                                rng.nextLong(PermutationGenerator.getTotalPermutations(inner)),
109                                inner,
110                                build);
111                build += inner;
112            }
113        }
114        int ilen = indexSections[0].length, ii = index / ilen, ij = index - ilen * ii;
115        ++index;
116        return elements.get(indexSections[ii][ij]);
117    }
118    /**
119     * Returns {@code true} if the iteration has more elements.
120     * This is always the case for GapShuffler.
121     *
122     * @return {@code true} always
123     */
124    @Override
125    public boolean hasNext() {
126        return true;
127    }
128    /**
129     * Not supported.
130     *
131     * @throws UnsupportedOperationException always throws this exception
132     */
133    @Override
134    public void remove() {
135        throw new UnsupportedOperationException("remove() is not supported");
136    }
137
138    /**
139     * Returns an <b>infinite</b> iterator over elements of type {@code T}; the returned iterator is this object.
140     * You should be prepared to break out of any for loops that use this once you've gotten enough elements!
141     * The remove() method is not supported by this iterator and hasNext() will always return true.
142     *
143     * @return an infinite Iterator over elements of type T.
144     */
145    @Override
146    public Iterator<T> iterator() {
147        return this;
148    }
149}


text:
::FactoryBot.define do
	factory :schedule do
		sequence(:next_due_date) { |n| (::Date.parse('2013-12-31') + n).to_s }
		frequency { 'Monthly' }
		estimate { true }
		auto_enter { true }
	end
end


text:
<?php

// No direct access
defined('_JEXEC') or die;
require_once JPATH_BASE.'/plugins/slogin_auth/yahoo/assets/yahoo-yos-social/lib/Yahoo/YahooOAuthApplication.class.php';
class plgSlogin_authYahoo extends JPlugin
{
    var $key,
        $secret,
        $app_id,
        $callback;
    function __construct(&$subject, $params)
	{
		parent::__construct( $subject, $params );
		$this->key = $this->params->get('key');
		$this->secret = $this->params->get('secret');
		$this->app_id = $this->params->get('app_id');
		$this->callback = JURI::base().'?option=com_slogin&task=check&plugin=yahoo';
	}
    public function onSloginAuth()
    {
        $oauthapp      = new YahooOAuthApplication($this->key, $this->secret, $this->app_id, $this->callback);
        # Fetch request token
        $request_token = $oauthapp->getRequestToken($this->callback);
        $session = JFactory::getSession();
        $session->set('request_token', serialize($request_token));
        # Redirect user to authorization url
        $redirect_url  = $oauthapp->getAuthorizationUrl($request_token);
        return $redirect_url;
    }
    public function onSloginCheck()
    {
        //получение значений из сессии
        $session = JFactory::getSession();
        $request_token = unserialize($session->get('request_token'));
        $oauthapp = new YahooOAuthApplication($this->key, $this->secret, $this->app_id, $this->callback);
        $input = JFactory::getApplication()->input;
        $oauth_verifier = $input->getString('oauth_verifier', '');
        # Exchange request token for authorized access token
        $access_token  = $oauthapp->getAccessToken($request_token, $oauth_verifier);
        # update access token
        $oauthapp->token = $access_token;
        # fetch user profile
        $profile = $oauthapp->getProfile();
        if (empty($profile)) {
            die('Error: profile empty');
        }

		//var_dump($profile);
		/*
		object(stdClass)#594 (1) {
		["profile"]=> object(stdClass)#593 (10) {
			["guid"]=> string(26) "YHDVXZ4H4LBJKT6NGXU5JQ537E"
			["ageCategory"]=> string(1) "A"
			["created"]=> string(20) "2014-11-24T05:48:59Z"
			["image"]=> object(stdClass)#592 (4) { ["height"]=> string(3) "192"
			["imageUrl"]=> string(56) "https://s.yimg.com/dh/ap/social/profile/profile_b192.png"
			["size"]=> string(7) "192x192" ["width"]=> string(3) "192" }
			["lang"]=> string(5) "en-US"
			["memberSince"]=> string(20) "2014-09-30T12:10:41Z"
			["nickname"]=> string(7) "Arkadiy"
			["profileUrl"]=> string(51) "http://profile.yahoo.com/YHDVXZ4H4LBJKT6NGXU5JQ537E"
			["isConnected"]=> string(5) "false"
			["bdRestricted"]=> string(4) "true" } }
		*/
        $returnRequest = new SloginRequest();
        $returnRequest->first_name  = isset($profile->profile->givenName) ? $profile->profile->givenName : $profile->profile->nickname;
        $returnRequest->last_name   = isset($profile->profile->familyName) ? $profile->profile->familyName : '';
        $returnRequest->email       = isset($profile->profile->emails->handle) ? $profile->profile->emails->handle : '';
        $returnRequest->id          = isset($profile->profile->guid) ? $profile->profile->guid : '';
        $returnRequest->real_name   = isset($profile->profile->givenName) ? $profile->profile->givenName : $profile->profile->nickname;
        $returnRequest->sex         = isset($profile->profile->gender) ? $profile->profile->gender : '';
        $returnRequest->display_name = $profile->profile->nickname;
        $returnRequest->all_request  = $profile->profile;
        return $returnRequest;
    }
    public function onCreateSloginLink(&$links, $add = '')
    {
        $i = count($links);
        $links[$i]['link'] = 'index.php?option=com_slogin&task=auth&plugin=yahoo' . $add;
        $links[$i]['class'] = 'yahooslogin';
        $links[$i]['plugin_name'] = 'yahoo';
    }
}