skaut / skautis Goto Github PK
View Code? Open in Web Editor NEWPHP knihovna pro připojení do skautISu
License: BSD 3-Clause "New" or "Revised" License
PHP knihovna pro připojení do skautISu
License: BSD 3-Clause "New" or "Revised" License
Ahoj,
dostal jsem se do faze kdy potrebuji vyresit tento problem, ktery jsem uz nejakou dobu odkladal. Bohuzel nedari se mi prijit na elegantni zpusob se zachovanim zpetne kompatibility.
$this->perStorage
ma z dob kdy tahle knihovna byla soucasti nejakeho Nette projektu par neuplne peknych vlastnosti.
Ktere se spoustou popularnich tropi problemy, protoze nepouzivaji magicke metody. (Symfony, Laravel, CodeIgniter, CakePHP, FuelPHP, Aura) [alespon podle skouknuti dokumentace dokumentace]
Pristup k nedefinovanym promenym a spolehani se na PHP ze z nich automaticky udela pole.
Kod
Zpusob jakym aplikace pracuje se session vubec nemusi mit z defaultni PHP session nic spolecneho.
Kod
Navrhovane reseni:
Vytvori se trida pro konfiguraci, ktera klidne muze implementovat ArrayAccess, ale has(),get(),set()
by bylo vhodnejsi. Ta trida bude implementovat Serializable interface.
Misto session dostane SkautIS SessionAdapter s metodou store('nazev', $object)
a retrieve('nazev')
. A s pomoci teto tridy vse ulozit v __destruct()
metode. A naopak pri __construct()
nacist.
Kdyz by se nejake zakladni adaptery pribalily do knihovny (pro $_SESSION a NETTE session treba) byly by nutne zmeny v kodu pro uzivatele knihovny minimalni.
Misto:
$storage = \Nette\Environment::getSession()->getSection("__" . __CLASS__);
$this->context->skautIS->setStorage($storage, TRUE);
By bylo
$section = \Nette\Environment::getSession()->getSection("__" . __CLASS__);
$storage = new \SkautIS\SessionAdapter\NetteAdapter($section);
$this->context->skautIS->setStorage($storage, TRUE);
Misto
$skautis = \SkautIS\SkautIS::getInstance()
By bylo
$skautis = \SkautIS\SkautIS::getInstance()
$storage = new \SkautIS\SessionAdapter\SessionAdapter();
$skautis->setStorage($storage);
Pres konfiguracni objekt je to vhodnejsi nez pristupovat primo k SessionAdapteru, protoze nektere implementace podporuji sekce a jine odlisnosti.
Reseni rad implementuji, ale nechtel jsem se do toho postet pred nejakou diskusi kdyz to neni zpetne kompatibilni.
Se zapnutým E_NOTICE to tady háže notice:
Chybí $s=""
.
Verze systémů:
Popis problému:
Snažím se rozjet SkautIS podle dokumentace (co jsem kde poshrabával místama), avšak narážím na následující problém při použití tohoto kusu kódu z readme.md:
$data = $skautis->user->UserDetail(array("ID"=>1940));
Vyhodí to v Nette vyjímku :"Notice: Array to string conversion as WS.php:92"
Kód okolo toho:
class SkautisPresenter extends BasePresenter
{
/** @var \SkautIS\SkautIS */
protected $skautIS;
/**
* Injects connection to IS skaut
*
* @param \SkautIS\SkautIS $skautIS
* @throws \Nette\InvalidStateException
*/
public function injectEvent(\SkautIS\SkautIS $skautIS){
if ($this->skautIS) {
throw new \Nette\InvalidStateException('SkautIS has already been set');
}
$this->skautIS = $skautIS;
}
public function actionDefault(){
$request = $this->request;
if ($request->getPost('skautIS_Token')
&& $request->getPost('skautIS_IDRole')
&& $request->getPost('skautIS_IDUnit')
){
$this->skautIS->setLoginData($request->getPost('skautIS_Token')
,$request->getPost('skautIS_IDRole')
,$request->getPost('skautIS_IDUnit'));
} elseif ($this->skautIS->isLoggedIn()){
$this->skautIS->updateLogoutTime();
} else {
$this->redirect('login');
}
}
public function renderDefault(){
$this->skautIS->getWsdlList();
$this->template->person = $this->skautIS->user->UserDetail(array("ID"=>1940));
}
/**
* Sets variable for view of "Default" page
*/
public function renderLogin()
{
$this->template->loginUrl = $this->skautIS->getLoginUrl();
}
Účelem je vážně jen nějaké řešení, které začne tahat opravdová data, abych se měl od čeho odpíchnout.
Ve verzi 3.0.0 alpha 1 je problém s parsováním output, pokud neobsahuje tag <...Output> - např.:
Undefined property: stdClass::$UserDetailOutput
Další problém je v typu, pokud se vrací $result (stdClass místo array)
...
$output = $result->{$fname . 'Output'};
if (!isset($output)) {
return $result; //neobsahuje $fname.Output
}
...
Druhý odkaz v docs/pouziti.md nefunguje (http://test-is.skaut.cz/JunakWebservice/). Nejsem si jist, ale myslím, že správná adresa by mohla být http://is.skaut.cz/napoveda/programatori.webservice.ashx.
Navrhuji do verze 3.x pridat Logovani pomoci PSR3.
Při použití testovacího SkautISu funkce vygeneruje adresu http://test-is.skaut.cz/Login/... na kterou SkautIS vrací 404 - Not Found. Je potřeba generovat URL s https scheme, pak to funguje.
Pracovni myslenka je podporovat batch request. Coz se da udelat pres cURL.
Samozrejme by zustala moznost synchroniho spracovani. I jako fallback kdy neni cURL k dispozici.
Jako transportni vrstva by se dala pouzit https://github.com/guzzle/guzzle
Jelikoz Guzzle by nevalidoval pozadavek vuci WSDL, dalo by se pouzit https://github.com/wsdl2phpgenerator/wsdl2phpgenerator
Rád bych navrhl pro verzi 3.0 výměnu Soap klienta. Je to něco, co minimálně ve svých projektech mám v plánu dělat, a tedy nabízím implementaci přímo tady. Rád bych využil buď Guzzle/PSR-7 (osobně mi přijde z uživatelského pohledu jednodušší mít závislost přímo na Guzzle), nebo např. meng-tian/async-soap-guzzle
HistoryMiddleware
apod). Kromě toho některé části ani nejdou namockovat (SoapClient při vytvoření instance stahuje wsdl soubor, což není možné nijak přetížit).Třída \SkautIS\Nette\Tracy\Panel
dědí z \DibiObject
, což je skrytá závislost na Dibi, která není uvedena v composer.json.
Nicméně je to zřejmě jediná závislost na Dibi, navíc celkem zbytečná. Stačilo by místo \DibiObject
použít \Nette\Object
a mělo by to být v cajku.
Verze 2.x i 3.x používají interface Serializable
, který je deprecated v PHP 8.1: https://php.watch/versions/8.1/serializable-deprecated
Mohl bys prosím doplnit nějaký ukázkový usecase? Třeba do /README.rst, pak se to hezky ukazuje při otevření repa. :-) Mně osobně jde pouze o přihlášení uživatele a vypsání jeho Person.
Dík
Navrhuji zvednout verzi na PHP 7.X. Pro kompatibilitu by bylo nejlepsi 7.0, ale 7.1 ma z meho pohledu znacne zlepseni (nullable, void, iterable typehinty)
Nevím přesně okolnosti, za kterých to nastává, ale někdy se může stát, že trace neobsahuje index 'line'
. Potom to zde hodí E_NOTICE:
Ahoj,
vzhledem k tomu, že vidím práci na verzi 3.0 bych chtěl navrhnout ke zvážení používání "magických" metod, konkrétně Skautis::__get()
. Já jsem na to konkrétně narazil v případě statické analýzy kódu, která je při použítí __get()
prakticky nemožná. Navíc mi obecně přijde, že to je spíš "code smell" a s verzí 3.0 může být jedinečná šance to změnit...
Pokud byste o tom uvažovali, rád se budu bavit o alternativách a případně pak udělám PR. Díky!
V nápovědě se píše o funkci setInit, ale nikde jsem ji nedohledal...
Ve vetsi aplikaci, nebo aplikaci hodne modulovane (pouzivajici framework) se casto stava ze se vola nektera funkce nekolikrat a diky slozeni z jednotlivych komponent je ponekud slozitejsi si jiz prenesena data predavat.
Priklad:
Prvni request bude trvat 150ms+ (stazeni wsdl)
Kazdy dalsi 60ms+
Coz dohromady dava 390ms misto 150.
Samozrejme za predpokladu ze je dobre pripojeni, Skautis je nezatizeny a slape rychle.
Coz samo o sobe neni prilis dlouho, ale kdyz se k tomu pricte prace DB, nejake to sahnuti na soubory v kombinaci s mobilnim pripojeni a programatorem zacatecnikem (nebo nemajicim cas optimalizovat) je z toho par sekundovy pozadavek, coz uz je problem.
Navrhoval bych pouziti cache pro jiz prenesena data, podobne jako maji ruzna ORM. Tak aby WebService pri stejnych requestech vracela odpoved z cache.
Implementaci bych navrhl pomoci decorator paternu, aby se dala tato funkce jednoduse pridat a jinak neprekazela.
V knihovne by meli existovat 2 predpripravene Cache implementace
Otazky ktere je potreba prvni zodpovedet:
Ukazka
class WebServiceCacheDecorator implements WebServiceInterface
{
/**
* @var Skautis\Wsdl\WebService
*/
protected $webService;
/**
* @var Skautis\CacheInterface
*/
protected $cache;
public function __get($functionName, $args)
{
if (isset($args['skautis_cache']) && $args['skautis_cache'] === false) {
unset($args['skautis_cache']);
return parent::__get($functionName, $args);
}
$sargs = $args;
ksort($sargs);
$jsonArgs = json_encode($sargs);
$hash = hash($functionName . $jsonArgs);
if ($this->cache->has($hash)) {
return $this->cache->get($hash);
}
else {
return parent::__get($functionName, $args);
}
}
}
Ahoj,
navrhuji doplnit možnost instalace pomocí composer + packagist (http://getcomposer.org/)
Velmi usnadňuje práci se závislostmi + class autoloading.
Je velmi využívaný např.: Drupal (8), phpBB, a naprostá většina frameworků Nette, Symfony, Zend, Laravel..
Pokud by o to byl zájem, rád to udělám a hodím pull request.
Mohu se zeptat co je za třídu BaseException
?
A druhy dotaz. K čemu má sloužit funkce setStorage?
Jelikoz se codebase rozrusta, je potreba rozhodnout o cofing style. Idealne mit i config pro PHP Code Sniffer / PHP Code Fixer.
Projekty pro urcity framework by meli pouzivat veci zabehle pro dany framework, takze se jedna hlavne o samostatnou knihovnu.
Krome stylu psani je potreba rozhodnout i o jednotnem pojmenovani.
Napriklad:
ISessionAdapter
vs SessionAdapterInterface
ASessionAdapter
vs AbstractSessionAdapter
Jako vyhodu delsiho zapisu vidim ze kazdy to muze precist bez znalosti toho prefixovani pismenem. Take mi prijde v PHP komunite rozsirenejsi (Symfony, Zend 2)
Nejlehci by bylo prevzit to od nejakeho projektu, jelikoz bychom nemuseli sepisovat pravidla a vytvaret config pro PHP Code Sniffer.
Takhle vypadaji nejake statistiky vuci PSR2.
Když se pokusí isMaintenance
získat headery Skautisu a serveru se nepodaří DNS lookup tak hodí warning:
Warning: get_headers(): php_network_getaddresses: getaddrinfo failed: Temporary failure in name resolution
Což podle toho jak aplikace řeší warningy může znamenat že se bude ignorovat, nebo třeba že se bude považovat za error a aplikace vrátí "Něco se rozbilo" místo toho aby prostě vypnula Skautis funkce a dál fungovala.
Osobně nechápu proč je tohle řešeno přes warning a ne exception.
Možné řešení:
set_error_handler(function() {});
$headers = get_headers($this->getWebServiceUrl("UserManagement"));
restore_error_handler();
return !is_array($headers) || !in_array('HTTP/1.1 200 OK', $headers);
To je nejsnazší, v případě problému se bude trvářit že Skautis je v údržbě a zbytek aplikace bude fungovat dál. Ale ztratí se informace co nešlo (DNS lookup) a metoda isMaintanance checkuje i něco co chekovat nemá.
Samozřejmě by šlo to transformovat do exceptionu což je o něco lepší, protože se dají hromadně chytat skautis exceptiony. Ale pořád je to nicmoc použití. Obzvláště když napojení na skautis je vedlejší funkcionalita a tedy to že se nelze připojit není problém ale je to potřeba vědět.
Př:
try {
if (!$this->skautis->isMaintanance() {
$this->updateUserInfoFromSkautis();
}
}
catch (\Skautis\Exception $e) {
//ignore nebo log
}
$this->displaySomePage();
Jelikož se pomalu hromadí projekty na github.com/skaut. Bylo by dobré mít věci přehledné.
Dobrým začátkem by bylo mít společené root namespace skaut.
Repozirář | Baliček | Kvalifikovaná hlavní třída |
---|---|---|
skaut/Skautis | skautis/skautis | Skautis\Skautis |
Repozirář | Baliček | Kvalifikovaná hlavní třída |
---|---|---|
skaut/skautis | skaut/skautis | Skaut\Skautis |
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.