Merge branch 'master' of https://bitbucket.org/1ka/1ka
This commit is contained in:
commit
7d5dc48bd7
@ -264,6 +264,8 @@ class SurveyAdmin
|
||||
global $global_user_id;
|
||||
global $lang;
|
||||
global $admin_type;
|
||||
global $site_domain;
|
||||
global $aai_instalacija;
|
||||
|
||||
$sql = sisplet_query("SELECT email FROM users WHERE id='$global_user_id'");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
@ -289,7 +291,8 @@ class SurveyAdmin
|
||||
|
||||
echo '<form method="GET" id="1kasf" action="'.$drupal_search_url.'">';
|
||||
|
||||
echo '<input type="hidden" id="drupal_search_url" name="drupal_search_url" value="'.$drupal_search_url.'" />';
|
||||
echo '<input type="hidden" id="drupal_search_url" name="drupal_search_url" value="'.$drupal_search_url.'" />';
|
||||
|
||||
echo '<a href="#" onclick="showSearch();"><span class="faicon search pointer"></span></a> ';
|
||||
echo '<input id="searchSurvey" type="text" value="" placeholder="' . $lang['s_search_frontend'] . '" name="search" />';
|
||||
echo '<input type="button" style="display: none;" value="' . $lang['s_search'] . '" />';
|
||||
@ -328,11 +331,15 @@ class SurveyAdmin
|
||||
|
||||
$text = $row['name'] . ' ' . $row['surname'];
|
||||
$text = (strlen($text) > 25) ? substr($text, 0, 25) . '...' : $text;
|
||||
|
||||
echo '<div id="xtradiv"><strong class="xtraname">' . $text . ' <span class="faicon after sort_down_arrow"/></strong>';
|
||||
echo '<div id="xtradivSettings">';
|
||||
|
||||
|
||||
echo '<div id="xtradiv"><strong class="xtraname">' . $text . ' <span class="faicon after sort_down_arrow"/></strong>';
|
||||
echo '<div id="xtradivSettings">';
|
||||
// Za Arnes.si skrijemo zavihek moj profil, da ne morejo spremijati gesla
|
||||
if($site_domain != '1ka.arnes.si') {
|
||||
echo '<span class="xtraSetting"><a class="xtra" href="' . $site_url . 'admin/survey/index.php?a=nastavitve&m=global_user_myProfile"><span class="faicon user"></span>' . $lang['edit_data'] . '</a></span>';
|
||||
|
||||
}
|
||||
|
||||
// Odjava na nov nacin preko frontend/api
|
||||
echo '<form name="odjava" method="post" action="'.$site_url.'frontend/api/api.php?action=logout">';
|
||||
echo '<span class="xtraSetting"><a class="xtra" href="#" onClick="document.odjava.submit();"><span class="faicon logout"></span>' . $lang['logout'] . '</a></span>';
|
||||
@ -371,7 +378,7 @@ class SurveyAdmin
|
||||
// Prikaze podatke o anketi in navigacijo - na vrhu (top bar)
|
||||
$this->displayAnketaTop();
|
||||
|
||||
echo '<div id="anketa_edit" class="page_'.$_GET['a'].' subpage_'.$_GET['m'].'">';
|
||||
echo '<div id="anketa_edit" class="page_'.$_GET['a'].' subpage_'.$_GET['m'].' '.($this->survey_type == '1' ? 'forma' : '').' '.($this->survey_type == '0' ? 'glasovanje' : '').'">';
|
||||
$this->displayAnketa();
|
||||
echo '</div>';
|
||||
|
||||
@ -564,6 +571,7 @@ class SurveyAdmin
|
||||
global $lang;
|
||||
global $app_settings;
|
||||
global $site_frontend;
|
||||
global $aai_instalacija;
|
||||
|
||||
echo '<div id="srv_footer">';
|
||||
|
||||
@ -579,11 +587,14 @@ class SurveyAdmin
|
||||
else{
|
||||
echo $lang['srv_footer_links'];
|
||||
|
||||
if(isset($aai_instalacija) && $aai_instalacija == true){
|
||||
echo ' | <a href="https://www.1ka.si/d/sl/pomoc/pogosta-vprasanja/pogosta-vprasanja-o-arnes-aai-prijavi-uporabi-orodja-1ka" target="_blank">'.$lang['aa4'].'</a>';
|
||||
}
|
||||
|
||||
echo '<br />';
|
||||
|
||||
// Verzijo izpišemo samo za admine
|
||||
if ($admin_type == 0) {
|
||||
|
||||
if ($admin_type == 0) {
|
||||
|
||||
// Verzija 1ka
|
||||
$sqlVersion = sisplet_query("SELECT value FROM misc WHERE what='version'", "obj");
|
||||
@ -613,6 +624,9 @@ class SurveyAdmin
|
||||
if (Common::checkModule('gorenje')){
|
||||
echo '<a href="https://helpdesk.gorenje.com/SubmitSR.jsp" target="_blank"><span class="faicon inline_comment"></span> '.$lang['srv_footer_reportabug'].'</a>';
|
||||
}
|
||||
elseif(isset($aai_instalacija) && $aai_instalacija == true){
|
||||
echo '<a href="https://www.1ka.si/help1KA" target="_blank"><span class="faicon inline_comment"></span> '.$lang['srv_footer_reportabug'].'</a>';
|
||||
}
|
||||
else{
|
||||
// Slovenski jezik
|
||||
if ($lang['id'] == 1)
|
||||
@ -906,7 +920,7 @@ class SurveyAdmin
|
||||
}
|
||||
# če je manj kot 20 variabel naj gre default na graf
|
||||
$sql = sisplet_query("SELECT COUNT(*) AS count FROM srv_spremenljivka s, srv_grupa g WHERE s.gru_id=g.id AND g.ank_id='$this->anketa'");
|
||||
list($varcount) = mysqli_fetch_array($sql);
|
||||
[$varcount] = mysqli_fetch_array($sql);
|
||||
|
||||
|
||||
if ($varcount < 20) {
|
||||
@ -1484,7 +1498,7 @@ class SurveyAdmin
|
||||
if ($this->survey_type > 1) {
|
||||
$str_testdata = "SELECT count(*) FROM srv_user WHERE ank_id='" . $this->anketa . "' AND (testdata='1' OR testdata='2') AND deleted='0'";
|
||||
$query_testdata = sisplet_query($str_testdata);
|
||||
list($testdata) = mysqli_fetch_row($query_testdata);
|
||||
[$testdata] = mysqli_fetch_row($query_testdata);
|
||||
|
||||
if ((int)$testdata > 0) {
|
||||
echo '<ul class="secondNavigationArchive">';
|
||||
@ -3258,7 +3272,7 @@ class SurveyAdmin
|
||||
*
|
||||
*/
|
||||
function displaySeznamAnket(){
|
||||
global $lang, $site_url, $global_user_id, $admin_type;
|
||||
global $lang, $site_url, $global_user_id, $admin_type, $site_domain;
|
||||
|
||||
// Pobrisemo vse preview vnose
|
||||
Common::deletePreviewData($this->anketa);
|
||||
@ -3383,11 +3397,11 @@ class SurveyAdmin
|
||||
elseif($_GET['m'] == 'odjavljeni'){
|
||||
$sas->unsignedUsersList();
|
||||
}
|
||||
elseif(in_array($_GET['m'], ['all', 'my'])){
|
||||
elseif($_GET['m'] == 'all'){
|
||||
$sas->allUsersList();
|
||||
}
|
||||
else {
|
||||
$sas->anketa_list_users();
|
||||
$sas->assignedUsersList();
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
@ -3465,7 +3479,7 @@ class SurveyAdmin
|
||||
$sas = new SurveyAdminSettings();
|
||||
$sas->globalUserSettings();
|
||||
}
|
||||
if ($_GET['m'] == 'global_user_myProfile') {
|
||||
if ($_GET['m'] == 'global_user_myProfile' && $site_domain != '1ka.arnes.si') {
|
||||
$sas = new SurveyAdminSettings();
|
||||
$sas->globalUserMyProfile();
|
||||
}
|
||||
@ -4167,7 +4181,7 @@ class SurveyAdmin
|
||||
$file = $site_path . 'main/survey/uploads/' . $logo;
|
||||
$fileExt = pathinfo($_FILES['fajl']['name'], PATHINFO_EXTENSION);
|
||||
|
||||
list($width, $height) = getimagesize($_FILES['fajl']['tmp_name']);
|
||||
[$width, $height] = getimagesize($_FILES['fajl']['tmp_name']);
|
||||
|
||||
// If logo too large resize uploaded logo to max 150px height
|
||||
if($height > 150){
|
||||
@ -4346,7 +4360,7 @@ class SurveyAdmin
|
||||
/**
|
||||
* @desc ustvari novo anketo
|
||||
*/
|
||||
function nova_anketa($naslov = null, $intro_opomba = '', $akronim = null, $survey_type = 2, $lang_resp = 1, $skin = '1kaBlue')
|
||||
function nova_anketa($naslov = null, $intro_opomba = '', $akronim = null, $survey_type = 2, $skin = '1kaBlue')
|
||||
{
|
||||
|
||||
global $lang;
|
||||
@ -4365,7 +4379,7 @@ class SurveyAdmin
|
||||
$lang_admin = $row['lang'];
|
||||
|
||||
$res = sisplet_query("SELECT value FROM misc WHERE what='SurveyCookie'");
|
||||
list ($SurveyCookie) = mysqli_fetch_row($res);
|
||||
[$SurveyCookie] = mysqli_fetch_row($res);
|
||||
|
||||
$text = '';
|
||||
$url = $site_url;
|
||||
@ -4381,10 +4395,10 @@ class SurveyAdmin
|
||||
|
||||
$starts = $_POST['starts'] ? "'" . $_POST['starts'] . "'" : "NOW()";
|
||||
$expire = $_POST['expire'] ? "'" . $_POST['expire'] . "'" : "NOW() + INTERVAL 3 MONTH ";
|
||||
#$expire = $_POST['expire'] ? "'" . $_POST['expire'] . "'" : "NOW() + INTERVAL 30 DAY ";
|
||||
|
||||
$lang_resp = ((int)$lang_resp > 0) ? $lang_resp : 1;
|
||||
// Nastavimo jezik - admin in response jezik je vedno enak nastavitvi, ki jo ima uporabnik a default
|
||||
$lang_admin = ((int)$lang_admin > 0) ? $lang_admin : 1;
|
||||
$lang_resp = $lang_admin;
|
||||
|
||||
# ali ima uporabnik nastavljeno da je anketa privzeto aktivna:
|
||||
$autoActiveSurvey = (int)UserSetting::getInstance()->getUserSetting('autoActiveSurvey');
|
||||
|
@ -597,19 +597,8 @@ class SurveyAdminAjax {
|
||||
if (!$sql)
|
||||
echo mysqli_error($GLOBALS['connect_db']);
|
||||
}
|
||||
if (isset ($_POST['SurveyLang_admin'])) {
|
||||
$val = $_POST['SurveyLang_admin'];
|
||||
$sql = sisplet_query("UPDATE misc SET value='$val' WHERE what = 'SurveyLang_admin'");
|
||||
if (!$sql)
|
||||
echo mysqli_error($GLOBALS['connect_db']);
|
||||
}
|
||||
if (isset ($_POST['SurveyLang_resp'])) {
|
||||
$val = $_POST['SurveyLang_resp'];
|
||||
$sql = sisplet_query("UPDATE misc SET value='$val' WHERE what = 'SurveyLang_resp'");
|
||||
if (!$sql)
|
||||
echo mysqli_error($GLOBALS['connect_db']);
|
||||
}
|
||||
} elseif ($_GET['m'] == 'global_user_settings') {
|
||||
}
|
||||
elseif ($_GET['m'] == 'global_user_settings') {
|
||||
if (isset ($_POST['language'])) {
|
||||
$lang = $_POST['language'];
|
||||
|
||||
@ -1755,7 +1744,7 @@ class SurveyAdminAjax {
|
||||
if (trim($_POST['survey_type']) == '') {
|
||||
$_POST['survey_type'] = 2;
|
||||
}
|
||||
$anketa = $this->SurveyAdmin->nova_anketa($naslov, $intro_opomba, $akronim, $_POST['survey_type'], $_POST['lang_resp'], $skin);
|
||||
$anketa = $this->SurveyAdmin->nova_anketa($naslov, $intro_opomba, $akronim, $_POST['survey_type'], $skin);
|
||||
|
||||
// Ce imamo pri ustvarjanju doloceno tudi mapo, anketo vstavimo v njo
|
||||
if(isset($_POST['folder']) && $_POST['folder'] > 0){
|
||||
@ -5134,10 +5123,6 @@ class SurveyAdminAjax {
|
||||
$s = sisplet_query("DELETE FROM srv_password WHERE ank_id='$this->anketa' AND password = '$password'");
|
||||
if (!$s) echo mysqli_error($GLOBALS['connect_db']);
|
||||
}
|
||||
} elseif ($_GET['a'] == 'refreshUserDiagnostic') {
|
||||
$sas = new SurveyAdminSettings();
|
||||
$sas->anketa_list_users();
|
||||
|
||||
} elseif ($_GET['a'] == 'getDataStatusTitles') {
|
||||
global $lang;
|
||||
$return = array();
|
||||
|
@ -4836,10 +4836,6 @@ class SurveyAdminSettings {
|
||||
list ($SurveyExport) = mysqli_fetch_row($result);
|
||||
$result = sisplet_query("SELECT value FROM misc WHERE what='SurveyForum'");
|
||||
list ($SurveyForum) = mysqli_fetch_row($result);
|
||||
$result = sisplet_query("SELECT value FROM misc WHERE what='SurveyLang_admin'");
|
||||
list ($SurveyLang_admin) = mysqli_fetch_row($result);
|
||||
$result = sisplet_query("SELECT value FROM misc WHERE what='SurveyLang_resp'");
|
||||
list ($SurveyLang_resp) = mysqli_fetch_row($result);
|
||||
|
||||
echo '<span class="nastavitveSpan1" ><label>' . $lang['SurveyDostop'] . ':</label></span>';
|
||||
?>
|
||||
@ -4888,55 +4884,8 @@ class SurveyAdminSettings {
|
||||
?>
|
||||
</select>
|
||||
</fieldset>
|
||||
<fieldset><legend><?=$lang['lang']?></legend>
|
||||
<?php
|
||||
|
||||
$lang_array = array();
|
||||
$lang_orig_id = $lang['id'];
|
||||
// Preberemo razpoložljive jezikovne datoteke
|
||||
if ($dir = opendir('../../lang')) {
|
||||
while (($file = readdir($dir)) !== false) {
|
||||
if ($file != '.' AND $file != '..') {
|
||||
if (is_numeric(substr($file, 0, strpos($file, '.')))) {
|
||||
$i = substr($file, 0, strpos($file, '.'));
|
||||
$file = '../../lang/'.$i.'.php';
|
||||
include($file);
|
||||
$lang_array[$lang['language']] = $i;
|
||||
}
|
||||
}
|
||||
}
|
||||
$file = '../../lang/'.$lang_orig_id.'.php';
|
||||
include($file); // naložimo nazaj trenutni languague file
|
||||
}
|
||||
|
||||
// Sortiramo lang datoteke po abecedi
|
||||
ksort($lang_array);
|
||||
|
||||
?>
|
||||
<span class="nastavitveSpan1" ><label><?=$lang['srv_language_admin']?>:</label></span>
|
||||
<select name="SurveyLang_admin">
|
||||
<?
|
||||
foreach ($lang_array AS $val => $key) {
|
||||
echo '<option value="'.$key.'"'.($SurveyLang_admin==$key?' selected':'').'>'.$val.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<br />
|
||||
|
||||
<span class="nastavitveSpan1" ><label><?=$lang['srv_language_respons']?>:</label></span>
|
||||
<select name="SurveyLang_resp">
|
||||
<?
|
||||
foreach ($lang_array AS $val => $key) {
|
||||
echo '<option value="'.$key.'"'.($SurveyLang_resp==$key?' selected':'').'>'.$val.'</option>';
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
<br />
|
||||
|
||||
<?php
|
||||
|
||||
echo '</fieldset>';
|
||||
|
||||
<?php
|
||||
echo '<fieldset>';
|
||||
echo '<legend>' . $lang['srv_edithelp'] . '</legend>';
|
||||
|
||||
@ -7214,7 +7163,6 @@ class SurveyAdminSettings {
|
||||
$arrayTestni = array();
|
||||
for ($i=1; $i<=$_POST['stevilo_vnosov']; $i++) {
|
||||
|
||||
// if(session_id() == '') {session_start();}
|
||||
session_start();
|
||||
$_SESSION['progressBar'][$this->anketa]['current'] = $i;
|
||||
session_commit();
|
||||
@ -7982,28 +7930,12 @@ class SurveyAdminSettings {
|
||||
header("Location: index.php?anketa=$this->anketa&a=testiranje&m=testnipodatki");
|
||||
|
||||
} elseif ($_GET['delete_testdata'] == 1 || $_GET['delete_autogen_testdata'] == 1) {
|
||||
|
||||
|
||||
// Komentarje moramo obdrzat - zato jih zacasno shranimo in na novo vstavimo
|
||||
/*$comment_bck = array();
|
||||
$sqlComment = sisplet_query("SELECT dt.vre_id AS vre_id, dt.text AS text, dt.usr_id AS usr_id FROM srv_data_text".$this->db_table." dt, srv_user u WHERE u.ank_id='$this->anketa' AND u.testdata='1' AND dt.usr_id=u.id AND dt.spr_id='0'");
|
||||
while($rowComment = mysqli_fetch_array($sqlComment)){
|
||||
$comment_bck[] = $rowComment;
|
||||
}*/
|
||||
|
||||
|
||||
if($_GET['delete_autogen_testdata'] == 1)
|
||||
sisplet_query("DELETE FROM srv_user WHERE ank_id='$this->anketa' AND testdata='2'");
|
||||
else
|
||||
sisplet_query("DELETE FROM srv_user WHERE ank_id='$this->anketa' AND (testdata='1' OR testdata='2')");
|
||||
|
||||
|
||||
// Komentarje nazaj vstavimo
|
||||
/*foreach($comment_bck as $comment){
|
||||
$sqlComment = sisplet_query("INSERT INTO srv_data_text".$this->db_table." (spr_id, vre_id, text, usr_id) VALUES ('0', '".$comment['vre_id']."', '".$comment['text']."', NULL)");
|
||||
}*/
|
||||
|
||||
|
||||
#datoteki z podatki moramo zgenerirati na novo
|
||||
sisplet_query("UPDATE srv_data_files SET head_file_time='0000-00-00', data_file_time='0000-00-00' WHERE sid='$this->anketa'");
|
||||
sisplet_query("COMMIT");
|
||||
@ -8136,9 +8068,7 @@ class SurveyAdminSettings {
|
||||
echo '</fieldset>';
|
||||
|
||||
echo '<p>'.$lang['srv_testni_nakonec'].'</p>';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8267,205 +8197,6 @@ class SurveyAdminSettings {
|
||||
echo '</fieldset>';
|
||||
}
|
||||
|
||||
function anketa_list_users() {
|
||||
global $lang, $global_user_id, $admin_type;
|
||||
|
||||
$_GET['show'] = isset($_POST['show']) && $_POST['show'] == 'all' ? 'all' : $_GET['show'];
|
||||
$_GET['limit'] = isset($_POST['limit']) ? $_POST['limit'] : $_GET['limit'];
|
||||
|
||||
if ($admin_type == 0) {
|
||||
echo '<h3>';
|
||||
|
||||
echo '<a href="index.php?a=diagnostics&t=uporabniki&m=my" '.($_GET['m']=='my'?'style="text-decoration:underline"':'').'>'.$lang['srv_users_added'].'</a>';
|
||||
|
||||
echo '<span class="spaceLeft">|</span>';
|
||||
|
||||
echo '<span class="spaceLeft"><a href="index.php?a=diagnostics&t=uporabniki&m=all" '.($_GET['m']=='all'?'style="text-decoration:underline"':'').'>'.$lang['srv_users_all'].'</a></span>';
|
||||
|
||||
echo '<br /><br />';
|
||||
|
||||
echo '</h3>';
|
||||
}
|
||||
|
||||
# povezava polj z polji iz baze za sortiranje
|
||||
$sort_by_array = array(
|
||||
'name'=>'u.name',
|
||||
'email'=>'u.email',
|
||||
'type'=>'u.type',
|
||||
//'cnt'=>'sa1.survey_count',
|
||||
//'archive'=>'sa2.survey_archive',
|
||||
'cnt'=>'d1.dostop_survey_count',
|
||||
'archive'=>'d2.dostop_survey_archive',
|
||||
'registred'=>'u.when_reg',
|
||||
'login'=>'u.last_login'
|
||||
);
|
||||
|
||||
$fields = array(
|
||||
'name'=>$lang['srv_survey_list_users_name'],
|
||||
'email'=>$lang['srv_survey_list_users_email'],
|
||||
'type'=>$lang['admin_type'],
|
||||
'cnt'=>$lang['srv_survey_list_users_survey_count'],
|
||||
'archive'=>$lang['srv_survey_list_users_survey_archive_count'],
|
||||
'registred'=>$lang['srv_survey_list_users_registred'],
|
||||
'login'=>$lang['srv_survey_list_users_last_login'],
|
||||
);
|
||||
|
||||
|
||||
$srt_field = isset($sort_by_array[$_POST['field']]) ? $_POST['field'] : 'cnt';
|
||||
$srt_type = isset($_POST['type']) && $_POST['type'] == 'asc' ? 'asc' : 'desc';
|
||||
|
||||
# omejitev uporabnikov kateri nimajo anket
|
||||
// pri managerjih naj bodo vsi, ker cene se ne vidijo novo dodani uporabniki
|
||||
#if ($admin_type == 0)
|
||||
# $limit_no_survey = ' WHERE sa1.survey_count > 0';
|
||||
#else
|
||||
$limit_no_survey = ' WHERE 1=1';
|
||||
|
||||
# izvedemo poljubno sortiranje
|
||||
$order_by = ' ORDER BY ' . $sort_by_array[$srt_field] . ' '. $srt_type;
|
||||
|
||||
// managerji in admini vidijo tudi svoje uporabnike
|
||||
if ($admin_type == 1 || $admin_type == 0) {
|
||||
$user_condition = " AND (u.id = '".$global_user_id."' OR u.id IN (SELECT user FROM srv_dostop_manage WHERE manager='".$global_user_id."') )";
|
||||
|
||||
# ostali uporabniki lahko vidijo samo svoje ankete
|
||||
} elseif ((int)$global_user_id > 0) {
|
||||
$user_condition = " AND u.id = '".$global_user_id."'";
|
||||
}
|
||||
|
||||
// Meta admini spet kao vidijo vse
|
||||
//if ( Dostop::isMetaAdmin() )
|
||||
// opcija za vse admine
|
||||
if ( $_GET['show'] == 'all')
|
||||
$user_condition = "";
|
||||
|
||||
//}
|
||||
#
|
||||
|
||||
// Stevilo prikazanih
|
||||
if(isset($_GET['limit'])){
|
||||
$limit = " LIMIT ".(int)$_GET['limit'];
|
||||
$limit_cnt = (int)$_GET['limit'];
|
||||
}
|
||||
else{
|
||||
$limit = " LIMIT 100";
|
||||
$limit_cnt = 100;
|
||||
}
|
||||
|
||||
// Stran (ce ne prikazujemo vseh)
|
||||
if(isset($_GET['page'])){
|
||||
$offset = " OFFSET ".(((int)$_GET['page']-1) * $limit_cnt);
|
||||
}
|
||||
else{
|
||||
$offset = " OFFSET 0";
|
||||
}
|
||||
|
||||
// Ce imamo iskanje izvedemo drugacen query
|
||||
if($admin_type == 0 && isset($_POST['search_users'])){
|
||||
// Po novem stejemo vse ankete z dostopom (ne samo tiste katerih je avtor)
|
||||
$sql_string = "SELECT u.id, u.type, u.status, u.email, u.name, u.surname, date_format(u.when_reg, '%d.%m.%Y') as when_reg, d1.dostop_survey_count, d2.dostop_survey_archive, date_format(u.last_login, '%d.%m.%Y') as last_login FROM users AS u "
|
||||
." LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_count FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup='0' GROUP BY srv_dostop.uid ) AS d1 ON d1.uid = u.id "
|
||||
." LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_archive FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup>'0' GROUP BY srv_dostop.uid ) AS d2 ON d2.uid = u.id "
|
||||
." WHERE u.email LIKE '%".$_POST['search_users']."%' OR u.name LIKE '%".$_POST['search_users']."%' OR u.surname LIKE '%".$_POST['search_users']."%' "
|
||||
. $order_by;
|
||||
}
|
||||
else{
|
||||
// Po novem stejemo vse ankete z dostopom (ne samo tiste katerih je avtor)
|
||||
$sql_string = "SELECT u.id, u.type, u.status, u.email, u.name, u.surname, date_format(u.when_reg, '%d.%m.%Y') as when_reg, d1.dostop_survey_count, d2.dostop_survey_archive, date_format(u.last_login, '%d.%m.%Y') as last_login FROM users AS u "
|
||||
." LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_count FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup='0' GROUP BY srv_dostop.uid ) AS d1 ON d1.uid = u.id "
|
||||
." LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_archive FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup>'0' GROUP BY srv_dostop.uid ) AS d2 ON d2.uid = u.id "
|
||||
. $limit_no_survey
|
||||
. $user_condition
|
||||
. $order_by
|
||||
. $limit . $offset;
|
||||
}
|
||||
|
||||
$sql_query = sisplet_query($sql_string);
|
||||
if (!$sql_query) echo mysqli_error($GLOBALS['connect_db']);
|
||||
|
||||
$sqlu = sisplet_query("SELECT * FROM users WHERE id = '$global_user_id'");
|
||||
$rowu = mysqli_fetch_array($sqlu);
|
||||
if ($admin_type == 0) {
|
||||
echo '<h2>'.$lang['administrator'].': '.$rowu['name'].' '.$rowu['surname'].'</h2>';
|
||||
} elseif ($admin_type == 1) {
|
||||
echo '<h2>'.$lang['manager'].': '.$rowu['name'].' '.$rowu['surname'].'</h2>';
|
||||
}
|
||||
|
||||
|
||||
echo '<table id="survey_list_users">';
|
||||
echo '<tr>';
|
||||
echo '<th></th>';
|
||||
foreach ($fields AS $field => $title) {
|
||||
echo '<th class="pointer">';
|
||||
if ($srt_field !== $field) {
|
||||
$img_src = 'sort_unsorted';
|
||||
echo '<div onClick="refresh_user_diagnostic(\''.$field.'\', \'desc\', \''.$_GET['show'].'\', \''.$_GET['limit'].'\')">'.$title.'</div>';
|
||||
} else {
|
||||
if ($srt_type == 'desc') {
|
||||
$img_src = 'sort_descending';
|
||||
echo '<div onClick="refresh_user_diagnostic(\''.$field.'\', \'asc\', \''.$_GET['show'].'\', \''.$_GET['limit'].'\')" class="red">'.$title.'<span class="faicon '.$img_src.'" title=""></span></div>';
|
||||
} else {
|
||||
$img_src = 'sort_ascending';
|
||||
echo '<div onClick="refresh_user_diagnostic(\''.$field.'\', \'desc\', \''.$_GET['show'].'\', \''.$_GET['limit'].'\')" class="red">'.$title.'<span class="faicon '.$img_src.'" title=""></span></div>';
|
||||
}
|
||||
}
|
||||
echo '</th>';
|
||||
}
|
||||
echo '</tr>';
|
||||
|
||||
while ($row_query = mysqli_fetch_array($sql_query)) {
|
||||
echo '<tr>';
|
||||
|
||||
echo '<td>';
|
||||
echo ' <a href="#" onclick="edit_user(\''.$row_query['id'].'\'); return false;" title="'.$lang['srv_profile_edit'].'"><span class="faicon users icon-as_link"></span></a>';
|
||||
echo '</td>';
|
||||
|
||||
echo '<td>';
|
||||
echo $row_query['name'].' '.$row_query['surname'];
|
||||
echo '</td>';
|
||||
|
||||
if ( true /*$_GET['show'] == '' or Dostop::isMetaAdmin()*/ ) {
|
||||
echo '<td><span class="as_link" onClick="surveyList_user(\'uid\',\''.$row_query['id'].'\'); window.location.href=\'index.php\';">' . $row_query['email'] . '</span></td>';
|
||||
} else {
|
||||
echo '<td><span>' . $row_query['email'] . '</span></td>';
|
||||
}
|
||||
|
||||
if ($row_query['type'] == '0') $type = $lang['admin_admin'];
|
||||
elseif ($row_query['type'] == '1') $type = $lang['admin_manager'];
|
||||
elseif ($row_query['type'] == '2') $type = $lang['admin_clan'];
|
||||
elseif ($row_query['type'] == '3') $type = $lang['admin_narocnik'];
|
||||
|
||||
echo '<td>' . $type . ' '.($row_query['status']==0?'<span class="sprites cross" title="'.$lang['srv_user_banned'].'"></span>':'').'</td>';
|
||||
echo '<td class="anl_ac">'.(int)$row_query['dostop_survey_count'].'</td>';
|
||||
echo '<td class="anl_ac">'.(int)$row_query['dostop_survey_archive'].'</td>';
|
||||
echo '<td class="anl_ac">'.$row_query['when_reg'].'</td>';
|
||||
echo '<td class="anl_ac">'.$row_query['last_login'].'</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
echo '</table>';
|
||||
|
||||
|
||||
// poiscemo uporabnike, ki imajo managerski pregled na uporabnikovimi anketami
|
||||
$sqlu = sisplet_query("SELECT u.id, u.name, u.surname, u.email FROM srv_dostop_manage m, users u WHERE u.id=m.manager AND m.user = '$global_user_id'");
|
||||
if ( mysqli_num_rows($sqlu) > 0 ) {
|
||||
|
||||
echo '<br><br><h3><b>'.$lang['srv_manager_manager'].':</b></h3>';
|
||||
|
||||
while ($rowu = mysqli_fetch_assoc($sqlu)) {
|
||||
|
||||
echo '<a href="ajax.php?t=dostop&a=edit_remove_user_manager&uid='.$rowu['id'].'" onclick="if ( confirm(\'?\')) { } else {return false;}"><span class="faicon delete"></span></a> '.$rowu['email'].' - '.$rowu['name'].' '.$rowu['surname'].'<br>';
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// managerji in admini lahko dodajajo uporabnike, ki jih nato managirajo
|
||||
$this->dodeljeniUporabniki();
|
||||
|
||||
// admin lahko doda novega uporabnika
|
||||
$this->dodajNovegaUporabnika();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uporabnik (administrator, manager) lahko dodajata nove uporabnike in jim dodelita dostop
|
||||
*/
|
||||
@ -8474,15 +8205,16 @@ class SurveyAdminSettings {
|
||||
global $lang;
|
||||
global $virtual_domain;
|
||||
|
||||
// admini in na virtualkah tudi managerji lahko dodajajo uporabnike, ki jih nato managirajo
|
||||
if( !($admin_type == 0 || ($admin_type == 1 && $virtual_domain == true)) )
|
||||
// admini lahko dodajajo uporabnike, ki jih nato managirajo
|
||||
if($admin_type != 0)
|
||||
return '';
|
||||
|
||||
echo '<div id="dodajanjeNovega">';
|
||||
|
||||
echo ' | <a href="#" onclick="$(\'#dodajanjeNovega\').slideToggle(); return false;">'.$lang['srv_users_add_new'].'</a><br><div id="dodajanjeNovega" '.(!empty($_GET['add']) && ($_GET['error']=='pass' || $_GET['error']=='email') ? '' : ' style="display: none"').'>';
|
||||
echo '<form class="manager_add_user" name="admin_add_user" action="ajax.php?t=dostop&a=add_new_user" method="post">';
|
||||
|
||||
echo '<form class="manager_add_user" action="ajax.php?t=dostop&a=add_new_user" method="post">';
|
||||
echo '<h3><b>'.$lang['srv_users_add_new_title'].'</b></h3>';
|
||||
|
||||
echo '<p><label for="email">'.$lang['email'].':</label><input type="email" id="email" name="email"> '.(!empty($_GET['add']) && $_GET['error']=='email'?'<span class="red">'.$lang['srv_added_false'].'</span>':'').'</p>';
|
||||
echo '<p><label for="name">'.$lang['name'].':</label><input type="text" id="name" name="name"></p>';
|
||||
echo '<p><label for="surname">'.$lang['surname'].':</label><input type="text" id="surname" name="surname"></p>';
|
||||
@ -8494,14 +8226,17 @@ class SurveyAdminSettings {
|
||||
<option value="2">'.$lang['srv_diagnostics_filter_lang_ang'].'</option>
|
||||
</select>
|
||||
</p>';
|
||||
echo '<p><button type="submit">'.$lang['add'].'</button></p>';
|
||||
|
||||
//echo '<p><button type="submit">'.$lang['add'].'</button></p>';
|
||||
echo '<p><div class="buttonwrapper floatLeft">';
|
||||
echo ' <a class="ovalbutton ovalbutton_orange" href="#" onclick="document.admin_add_user.submit();">'.$lang['create'].'</a>';
|
||||
echo '</div></p>';
|
||||
|
||||
echo '</form>';
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Uporabnik (administrator, manager) lahko dodajata nove uporabnike in jim dodelita dostop
|
||||
*/
|
||||
@ -8509,38 +8244,83 @@ class SurveyAdminSettings {
|
||||
global $admin_type;
|
||||
global $lang;
|
||||
global $global_user_id;
|
||||
global $virtual_domain;
|
||||
|
||||
// managerji in admini lahko dodajajo uporabnike, ki jih nato managirajo
|
||||
if( !($admin_type == 1 || $admin_type == 0) )
|
||||
return '';
|
||||
|
||||
// Na virtualkah imajo managerji omejitev st. dodeljenih uporabnikov
|
||||
if(/*$virtual_domain && */$admin_type == 1){
|
||||
|
||||
echo '<br><br><a href="#" onclick="$(\'#dodajanje\').slideToggle(); return false;">'.$lang['srv_invitation_system_validateAndAdd'].'</a><div id="dodajanje" '.(empty($_GET['add']) && ($_GET['error']=='pass' || $_GET['error']=='email') ? '' : ' style="display: none"').'>';
|
||||
// Limit st. dodeljenih uporabnikov
|
||||
$managed_accounts_limit = 5;
|
||||
|
||||
echo '<form class="manager_add_user" action="ajax.php?t=dostop&a=manager_add_user" method="post">';
|
||||
echo '<h3><b>'.$lang['srv_manager_add_user'].'</b></h3>';
|
||||
// Prestejemo dodeljene uporabnike
|
||||
$sql = sisplet_query("SELECT u.email
|
||||
FROM srv_dostop_manage m, users u
|
||||
WHERE m.manager='".$global_user_id."' AND u.id=m.user AND u.email NOT LIKE ('D3LMD-%') AND u.email NOT LIKE ('UNSU8MD-%')
|
||||
");
|
||||
|
||||
$managed_accounts_count = mysqli_num_rows($sql);
|
||||
|
||||
|
||||
echo '<p class="bold" style="padding-left:0px;">';
|
||||
echo $lang['srv_users_add_assigned_max_1'].' <span class="red bold">'.$managed_accounts_limit.'</span> '.$lang['srv_users_add_assigned_max_2'];
|
||||
|
||||
// Manager na virtualkah ima omejitev koliko uporabnikov lahko pregleduje
|
||||
if($managed_accounts_count >= $managed_accounts_limit){
|
||||
echo '<br /><br />';
|
||||
echo $lang['srv_users_add_assigned_max_reached'];
|
||||
echo '</p>';
|
||||
|
||||
return;
|
||||
}
|
||||
elseif($managed_accounts_count > 0){
|
||||
echo '<br /><br />';
|
||||
echo $lang['srv_users_add_assigned_current'].' <span class="red bold">'.$managed_accounts_count.' '.$lang['of'].' '.$managed_accounts_limit.'</span>';
|
||||
}
|
||||
|
||||
echo '</p>';
|
||||
}
|
||||
|
||||
echo '<div id="dodajanje">';
|
||||
|
||||
echo '<form class="manager_add_user" name="manager_add_user" action="ajax.php?t=dostop&a=manager_add_user" method="post">';
|
||||
echo '<h3><b>'.$lang['srv_users_add_assigned_title'].'</b></h3>';
|
||||
echo '<p><label for="email">'.$lang['email'].':</label><input type="email" id="email" name="email"> '.(empty($_GET['add']) && $_GET['error']=='email'?'<span class="red">'.$lang['srv_added_false'].'</span>':'').'</p>';
|
||||
echo '<p><label for="name">'.$lang['name'].':</label><input type="text" id="name" name="name"></p>';
|
||||
echo '<p><label for="surname">'.$lang['surname'].':</label><input type="text" id="surname" name="surname"></p>';
|
||||
echo '<p><label for="password">'.$lang['password'].':</label><input type="password" id="password" name="password"> '.(empty($_GET['add']) && $_GET['error']=='pass'?'<span class="red">'.$lang['pass_doesnt_match'].'</span>':'').'</p>';
|
||||
echo '<p><label for="password2">'.$lang['again'].':</label><input type="password" id="password2" name="password2"></p>';
|
||||
echo '<p><button type="submit">'.$lang['add'].'</button></p>';
|
||||
|
||||
//echo '<p><button type="submit">'.$lang['add'].'</button></p>';
|
||||
echo '<p><div class="buttonwrapper floatLeft">';
|
||||
echo ' <a class="ovalbutton ovalbutton_orange" href="#" onclick="document.manager_add_user.submit();">'.$lang['create_add'].'</a>';
|
||||
echo '</div></p>';
|
||||
|
||||
echo '</form>';
|
||||
|
||||
// admini si lahko dodajajo ze obstojece uporabnike
|
||||
if ($admin_type == 0) {
|
||||
|
||||
echo '<br><form class="manager_add_user" action="ajax.php?t=dostop&a=admin_add_user" method="post">';
|
||||
echo '<br /><br /><br />';
|
||||
|
||||
echo '<form class="manager_add_user" name="admin_add_dostop" action="ajax.php?t=dostop&a=admin_add_user" method="post">';
|
||||
|
||||
echo '<h3><b>'.$lang['srv_manager_add_user2'].'</b></h3>';
|
||||
echo '<p><select name="uid" class="js-obstojeci-uporabniki-admin-ajax" style="width: 500px;"></select></p>';
|
||||
echo '<p><button type="submit">'.$lang['add'].'</button></p>';
|
||||
|
||||
//echo '<p><button type="submit">'.$lang['add'].'</button></p>';
|
||||
echo '<p><div class="buttonwrapper floatLeft">';
|
||||
echo ' <a class="ovalbutton ovalbutton_orange" href="#" onclick="document.admin_add_dostop.submit();">'.$lang['add'].'</a>';
|
||||
echo '</div></p>';
|
||||
|
||||
echo '</form>';
|
||||
}
|
||||
// Managerji lahko dodajajo samo uporabnike z dolocenimi emaili (če jim domeno posebej nastavi admin)
|
||||
// TODO: trenutno onemogočimo dodaja ostalih uporabnikov za managerje. Ko bo stvar vezana na domeno se jim bo omogočilo dodajanje samo domenskih
|
||||
elseif(false && $admin_type == 1){
|
||||
/*elseif(false && $admin_type == 1){
|
||||
|
||||
UserSetting :: getInstance()->Init($global_user_id);
|
||||
$emails = UserSetting :: getInstance()->getUserSetting('manage_domain');
|
||||
@ -8551,7 +8331,7 @@ class SurveyAdminSettings {
|
||||
echo '<p><button type="submit" id="manager-email-submit" style="display:none;">'.$lang['add'].'</button></p>';
|
||||
|
||||
echo '</form>';
|
||||
}
|
||||
}*/
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
@ -8559,43 +8339,102 @@ class SurveyAdminSettings {
|
||||
/**
|
||||
* Seznam vseh uporabnikov znotraj 1ke
|
||||
*/
|
||||
public function allUsersList()
|
||||
{
|
||||
public function allUsersList(){
|
||||
global $lang;
|
||||
global $admin_type;
|
||||
|
||||
echo '<a href="index.php?a=diagnostics&t=uporabniki&m=my" '.($_GET['m']=='my'?'style="text-decoration:underline"':'').'>'.$lang['srv_users_added'].'</a>';
|
||||
echo '<table id="all_users_list" class="dataTable">';
|
||||
|
||||
echo '<thead><tr>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_name'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_email'] . '</th>';
|
||||
echo '<th>' . $lang['admin_type'] . '</th>';
|
||||
echo '<th>' . $lang['lang'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_aai'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_survey_count'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_survey_archive_count'] . '</th>';
|
||||
echo '<th>' . $lang['users_gdpr_title'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_registred'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_last_login'] . '</th>';
|
||||
echo '<th style="max-width: 70px;">'.$lang['edit2'].'</th>';
|
||||
echo '</tr></thead>';
|
||||
|
||||
echo '</table>';
|
||||
|
||||
// Dodajanje uporabnikov
|
||||
echo '<div class="add_user">';
|
||||
|
||||
if($admin_type == 0) {
|
||||
echo '<span class="spaceLeft">|</span>';
|
||||
echo '<span class="spaceLeft"><a href="index.php?a=diagnostics&t=uporabniki&m=all" '.($_GET['m'] == 'all' ? 'style="text-decoration:underline"' : '').'>'.$lang['srv_users_all'].'</a></span>';
|
||||
}
|
||||
echo '<br /><br />';
|
||||
// Admin lahko doda novega uporabnika v sistem (brez pregleda)
|
||||
if($admin_type == '0'){
|
||||
echo '<fieldset class="new_user"><legend>'.$lang['srv_users_add_new'].'</legend>';
|
||||
$this->dodajNovegaUporabnika();
|
||||
echo '</fieldset>';
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Osnovni pregled uporabnikov za managerje in admine
|
||||
*/
|
||||
public function assignedUsersList(){
|
||||
global $lang;
|
||||
global $admin_type;
|
||||
global $global_user_id;
|
||||
|
||||
$sqlU = sisplet_query("SELECT name, surname, email FROM users WHERE id='".$global_user_id."'");
|
||||
$rowU = mysqli_fetch_array($sqlU);
|
||||
|
||||
|
||||
// Naslov
|
||||
echo '<h2 style="margin-bottom:30px;">';
|
||||
|
||||
if($admin_type == 0)
|
||||
echo $lang['administrator'];
|
||||
elseif($admin_type == 1)
|
||||
echo $lang['manager'];
|
||||
else
|
||||
echo $lang['user'];
|
||||
|
||||
echo ': '.$rowU['name'].' '.$rowU['surname'].' ('.$rowU['email'].')';
|
||||
|
||||
echo ' <a href="#" onclick="edit_user(\''.$global_user_id.'\'); return false;" title="Uredi"><i class="fa fa-pencil-alt link-moder"></i></a>';
|
||||
|
||||
echo '</h2>';
|
||||
|
||||
|
||||
echo '<table id="'.($_GET['m'] == 'all' ? 'all_users_list' : 'my_users_list').'" class="dataTable">';
|
||||
echo '<thead><tr>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_name'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_email'] . '</th>';
|
||||
echo '<th>' . $lang['admin_type'] . '</th>';
|
||||
echo '<th>' . $lang['lang'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_aai'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_survey_count'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_survey_archive_count'] . '</th>';
|
||||
echo '<th>' . $lang['users_gdpr_title'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_registred'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_last_login'] . '</th>';
|
||||
echo '<th style="max-width: 70px;">'.$lang['edit2'].'</th>';
|
||||
echo '</tr></thead>';
|
||||
echo '</table>';
|
||||
// Tabela
|
||||
echo '<fieldset style="max-width: 100% !important;"><legend>'.$lang['srv_users_assigned_title'].'</legend>';
|
||||
//echo '<h4 style="margin-bottom: 10px;">'.$lang['srv_users_assigned_title'].'</h4>';
|
||||
echo '<table id="my_users_list" class="dataTable">';
|
||||
|
||||
echo '<thead><tr>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_name'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_email'] . '</th>';
|
||||
echo '<th>' . $lang['admin_type'] . '</th>';
|
||||
echo '<th>' . $lang['lang'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_aai'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_survey_count'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_survey_archive_count'] . '</th>';
|
||||
echo '<th>' . $lang['users_gdpr_title'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_registred'] . '</th>';
|
||||
echo '<th>' . $lang['srv_survey_list_users_last_login'] . '</th>';
|
||||
echo '<th style="max-width: 70px;">'.$lang['edit2'].'</th>';
|
||||
echo '</tr></thead>';
|
||||
|
||||
echo '</table>';
|
||||
echo '</fieldset>';
|
||||
|
||||
|
||||
// Dodajanje uporabnikov
|
||||
echo '<div class="add_user">';
|
||||
|
||||
// Manager ali admin lahko doda novega uporabnika pod pregled
|
||||
echo '<fieldset class="assign_user"><legend>'.$lang['srv_users_add_assigned'].'</legend>';
|
||||
$this->dodeljeniUporabniki();
|
||||
echo '</fieldset>';
|
||||
|
||||
// admin lahko doda novega uporabnika
|
||||
$this->dodajNovegaUporabnika();
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
@ -9357,14 +9196,7 @@ class SurveyAdminSettings {
|
||||
echo '<input name="lockSurvey" type="checkbox" value="1" '.($lockSurvey == 1?' checked="checked"':'').'></label>';
|
||||
|
||||
echo '<br />';
|
||||
|
||||
// Napredni vmesnik (star design za moje ankete) - TEGA NIMAMO VEC (PUSTIMO SAMO KODO V OZADJU, CE BI KDAJ VASJA HOTEL NAZAJ:))
|
||||
/*echo '<label><span class="nastavitveSpan6">'.$lang['srv_settings_advancedMySurveys'].':</span>';
|
||||
echo '<input name="advancedMySurveys" type="hidden" value="0">';
|
||||
echo '<input name="advancedMySurveys" type="checkbox" value="1" '.($advancedMySurveys == 1?' checked="checked"':'').'></label>';
|
||||
|
||||
echo '<br />';*/
|
||||
|
||||
|
||||
// Opcija enklik ustvarjanja ankete (v mojih anketah)
|
||||
echo '<label><span class="nastavitveSpan6">'.$lang['srv_settings_oneClickCreate'].':</span>';
|
||||
echo '<input name="oneclickCreateMySurveys" type="hidden" value="0">';
|
||||
|
@ -33,7 +33,6 @@ if ($anketa > 0) {
|
||||
$lang_admin = $row['lang_admin'];
|
||||
}
|
||||
if ($lang_admin == 0) {
|
||||
//$sql = sisplet_query("SELECT * FROM misc WHERE what = 'SurveyLang_admin'");
|
||||
$sql = sisplet_query("SELECT lang FROM users WHERE id = '$global_user_id'");
|
||||
$row = @mysqli_fetch_array($sql);
|
||||
$lang_admin = $row['lang'];
|
||||
|
@ -1560,7 +1560,7 @@ class Common {
|
||||
}
|
||||
|
||||
//Users
|
||||
else if ($_GET['a'] == 'diagnostics' && $_GET['t'] == 'uporabniki' && (in_array($_GET['m'], array('my', 'izbrisani', 'nepotrjeni', 'odjavljeni', 'sa-modul'))) ) {
|
||||
else if ($_GET['a'] == 'diagnostics' && $_GET['t'] == 'uporabniki') {
|
||||
$help_url = 'https://www.1ka.si/d/en/help/user-guide/my-surveys/users';
|
||||
}
|
||||
|
||||
@ -1982,7 +1982,7 @@ class Common {
|
||||
}
|
||||
|
||||
//Uporabniki
|
||||
else if ($_GET['a'] == 'diagnostics' && $_GET['t'] == 'uporabniki' && (in_array($_GET['m'], array('my', 'izbrisani', 'nepotrjeni', 'odjavljeni', 'sa-modul'))) ) {
|
||||
else if ($_GET['a'] == 'diagnostics' && $_GET['t'] == 'uporabniki') {
|
||||
$help_url = 'https://www.1ka.si/d/sl/pomoc/vodic-za-uporabnike/moje-ankete/uporabniki';
|
||||
}
|
||||
|
||||
|
@ -229,16 +229,18 @@ class Dostop {
|
||||
} elseif ($_GET['a'] == 'all_users_list') {
|
||||
if ($_GET['m'] == 'delete') {
|
||||
$this->ajax_all_users_list_delete();
|
||||
}if ($_GET['m'] == 'ban') {
|
||||
}
|
||||
if ($_GET['m'] == 'ban') {
|
||||
$this->ajax_all_users_list_ban();
|
||||
}else {
|
||||
}
|
||||
else {
|
||||
$this->ajax_all_users_list();
|
||||
}
|
||||
|
||||
} elseif($_GET['a'] == 'my_users_list'){
|
||||
$this->ajax_all_users_list(true);
|
||||
$this->ajax_all_users_list_my();
|
||||
|
||||
}elseif ($_GET['a'] == 'delete_users_list') {
|
||||
} elseif ($_GET['a'] == 'delete_users_list') {
|
||||
$this->ajax_delete_users_list();
|
||||
|
||||
} elseif ($_GET['a'] == 'unsigned_users_list') {
|
||||
@ -247,9 +249,11 @@ class Dostop {
|
||||
} elseif ($_GET['a'] == 'unconfirmed_mail_user_list') {
|
||||
if ($_GET['m'] == 'delete') {
|
||||
$this->ajax_unconfirmed_mail_user_list_delet_user();
|
||||
} elseif ($_GET['m'] == 'accept') {
|
||||
}
|
||||
elseif ($_GET['m'] == 'accept') {
|
||||
$this->ajax_confirm_user_email();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$this->ajax_unconfirmed_mail_user_list();
|
||||
}
|
||||
}
|
||||
@ -380,7 +384,7 @@ class Dostop {
|
||||
{
|
||||
global $pass_salt;
|
||||
global $lang;
|
||||
global $global_user_id, $site_path;
|
||||
global $global_user_id, $site_path, $site_domain;
|
||||
global $admin_type;
|
||||
|
||||
$error = FALSE;
|
||||
@ -423,13 +427,20 @@ class Dostop {
|
||||
echo mysqli_error($GLOBALS['connect_db']);
|
||||
}
|
||||
|
||||
$subject = $lang['srv_dodanmail_1'] . '';
|
||||
$content = sprintf($lang['srv_dodanmail_2'], $MailReply) . '<br /><br />' . sprintf($lang['srv_dodanmail_3'], $email, $password);
|
||||
$subject = sprintf($lang['srv_dodanmail_1'], $site_domain);
|
||||
|
||||
$content = sprintf($lang['srv_dodanmail_2'], $MailReply, $site_domain).'<br /><br />';
|
||||
$content .= $lang['srv_dodanmail_3'];
|
||||
$content .= '<ul>';
|
||||
$content .= '<li>'.$lang['srv_dodanmail_3_email'].' <b>'.$email.'</b></li>';
|
||||
$content .= '<li>'.$lang['srv_dodanmail_3_pass_1'].' <b>'.$password.'</b> ('.$lang['srv_dodanmail_3_pass_2'].')</li>';
|
||||
$content .= '</ul>';
|
||||
|
||||
// Podpis
|
||||
$signature = Common::getEmailSignature();
|
||||
$content .= $signature;
|
||||
|
||||
|
||||
// Posljemo mail vsakemu uporabniku posebej
|
||||
try {
|
||||
$MA = new MailAdapter($this->anketa, $type='account');
|
||||
@ -477,10 +488,7 @@ class Dostop {
|
||||
|
||||
echo '<h3><span class="bold">';
|
||||
|
||||
if ($r['type'] == 2) {
|
||||
echo $lang['admin_clan'];
|
||||
}
|
||||
elseif ($r['type'] == 3) {
|
||||
if ($r['type'] == 2 || $r['type'] == 3) {
|
||||
echo $lang['admin_narocnik'];
|
||||
}
|
||||
elseif ($r['type'] == 1) {
|
||||
@ -661,6 +669,7 @@ class Dostop {
|
||||
global $lang;
|
||||
global $global_user_id;
|
||||
global $admin_type;
|
||||
global $virtual_domain;
|
||||
|
||||
$uid = $_POST['uid'];
|
||||
|
||||
@ -733,9 +742,13 @@ class Dostop {
|
||||
echo '<p><label for="manage_domain" style="width:200px;">Manager domene (npr. 1ka.si):</label><input type="text" id="manage_domain" name="manage_domain" value="' . $emails . '" autocomplete="off" size="30"></p>';
|
||||
}
|
||||
|
||||
$sqlu = sisplet_query("SELECT * FROM srv_dostop_manage WHERE manager='$global_user_id' AND user='$uid'");
|
||||
if (mysqli_num_rows($sqlu) > 0) {
|
||||
echo '<p><a href="ajax.php?t=dostop&a=edit_remove_user&uid=' . $uid . '" onclick="if ( confirm(\'?\')) { } else {return false;}">' . $lang['srv_manager_rem_user2'] . '</a></p>';
|
||||
// Na virtualkah manager ne sme odstraniti uporabnika iz pregleda (zaradi omejitve)
|
||||
if($admin_type != '1' || !$virtual_domain){
|
||||
$sqlu = sisplet_query("SELECT * FROM srv_dostop_manage WHERE manager='$global_user_id' AND user='$uid'");
|
||||
|
||||
if (mysqli_num_rows($sqlu) > 0) {
|
||||
echo '<br /><p><a href="ajax.php?t=dostop&a=edit_remove_user&uid=' . $uid . '" onclick="if ( confirm(\'?\')) { } else {return false;}">' . $lang['srv_manager_rem_user2'] . '</a></p>';
|
||||
}
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
@ -962,7 +975,7 @@ class Dostop {
|
||||
}
|
||||
}
|
||||
|
||||
//header("Location: index.php?a=diagnostics&t=uporabniki&m=my&error=" . ($error !== FALSE ? $error : ''));
|
||||
header("Location: index.php?a=diagnostics&t=uporabniki".($error !== FALSE ? '&error='.$error : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1043,120 +1056,104 @@ class Dostop {
|
||||
/**
|
||||
* Seznam vseh uporabnikov znotrja 1ke
|
||||
*/
|
||||
function ajax_all_users_list($my = null)
|
||||
{
|
||||
function ajax_all_users_list(){
|
||||
global $admin_languages;
|
||||
global $global_user_id;
|
||||
global $lang;
|
||||
global $admin_type;
|
||||
global $admin_type;
|
||||
|
||||
$seznam = [];
|
||||
|
||||
$iskanjeSql = "";
|
||||
if(!empty($_POST['search']['value'])){
|
||||
$iskaniNiz = $_POST['search']['value'];
|
||||
$iskanjeSql = " AND (u.name LIKE '%".$iskaniNiz."%' OR u.surname LIKE '%".$iskaniNiz."%' OR u.email LIKE '%".$iskaniNiz."%' OR d1.dostop_survey_count LIKE '%".$iskaniNiz."%' OR d2.dostop_survey_archive LIKE '%".$iskaniNiz."%')";
|
||||
}
|
||||
|
||||
// Pridobimo vse uporabnike
|
||||
$sql ="SELECT u.id as id, u.type as type, u.status, u.email as email, u.name as name, u.surname as surname, u.lang as lang, u.eduroam as aai, date_format(u.when_reg, '%d.%m.%Y') as registriran, u.gdpr_agree as gdpr_agree, d1.dostop_survey_count as st_anket, d2.dostop_survey_archive as st_arhivskih, date_format(u.last_login, '%d.%m.%Y') as last_login, ue.email as second_email FROM users AS u ".
|
||||
" LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_count FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup='0' GROUP BY srv_dostop.uid ) AS d1 ON d1.uid = u.id ".
|
||||
" LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_archive FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup>'0' GROUP BY srv_dostop.uid ) AS d2 ON d2.uid = u.id ".
|
||||
" LEFT OUTER JOIN (SELECT user_emails.email, user_emails.user_id FROM user_emails WHERE active=1) AS ue ON ue.user_id = u.id".
|
||||
" WHERE u.email NOT LIKE ('D3LMD-%') AND u.email NOT LIKE ('UNSU8MD-%') ".$iskanjeSql;
|
||||
|
||||
// Filter samo po lastnih uporabnikih
|
||||
if(!empty($my)){
|
||||
// Med lastne uporabnike prikažemo tudi, tiste ki so bili registrirani z isto domeno
|
||||
UserSetting :: getInstance()->Init($global_user_id);
|
||||
$domena = UserSetting :: getInstance()->getUserSetting('manage_domain');
|
||||
|
||||
$isciPoDomeni = '';
|
||||
if(!empty($domena)){
|
||||
$isciPoDomeni = " OR u.email LIKE '%".$domena."'";
|
||||
}
|
||||
|
||||
// Pridobimo vse uporabnike
|
||||
$sql = "SELECT u.id as id, u.type as type, u.status, u.email as email, u.name as name, u.surname as surname, u.lang as lang, u.eduroam as aai, date_format(u.when_reg, '%d.%m.%Y') as registriran, u.gdpr_agree as gdpr_agree, d1.dostop_survey_count as st_anket, d2.dostop_survey_archive as st_arhivskih, date_format(u.last_login, '%d.%m.%Y') as last_login, ue.email as second_email FROM users AS u ".
|
||||
" LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_count FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup='0' GROUP BY srv_dostop.uid ) AS d1 ON d1.uid = u.id ".
|
||||
" LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_archive FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup>'0' GROUP BY srv_dostop.uid ) AS d2 ON d2.uid = u.id ".
|
||||
" LEFT OUTER JOIN (SELECT user_emails.email, user_emails.user_id FROM user_emails WHERE active=1) AS ue ON ue.user_id = u.id".
|
||||
" WHERE u.email NOT LIKE ('D3LMD-%') AND u.email NOT LIKE ('UNSU8MD-%') ".$iskanjeSql;
|
||||
|
||||
$sql .= " AND (u.id = '".$global_user_id."' OR u.id IN (SELECT user FROM srv_dostop_manage WHERE manager='".$global_user_id."') ".$isciPoDomeni.")";
|
||||
}
|
||||
// Filtri, ki jih datatables pošilja in po katerih filtriramo
|
||||
if($_POST['order'][0]['column'] < 10) {
|
||||
$orderPolje = [
|
||||
"u.name ".$_POST['order'][0]['dir'].", u.surname",
|
||||
"u.email",
|
||||
"u.type",
|
||||
"u.lang",
|
||||
"u.eduroam", //AAI
|
||||
"d1.dostop_survey_count", //st_anket
|
||||
"d2.dostop_survey_archive", //st_arhivskih
|
||||
"u.gdpr_agree",
|
||||
"u.when_reg",
|
||||
"u.last_login"
|
||||
];
|
||||
|
||||
if($_POST['order'][0]['column'] == 7){
|
||||
|
||||
// Filtri, ki jih datatables pošilja in po katerih filtriramo
|
||||
if($_POST['order'][0]['column'] < 10) {
|
||||
$orderPolje = [
|
||||
"u.name ".$_POST['order'][0]['dir'].", u.surname",
|
||||
"u.email",
|
||||
"u.type",
|
||||
"u.lang",
|
||||
"u.eduroam", //AAI
|
||||
"d1.dostop_survey_count", //st_anket
|
||||
"d2.dostop_survey_archive", //st_arhivskih
|
||||
"u.gdpr_agree",
|
||||
"u.when_reg",
|
||||
"u.last_login"
|
||||
];
|
||||
$vrednost='u.gdpr_agree desc';
|
||||
if($_POST['order'][0]['dir'] == 'asc'){
|
||||
$vrednost= ' FIELD (u.gdpr_agree, 0, \'-1\', 1)';
|
||||
}
|
||||
|
||||
if($_POST['order'][0]['column'] == 7){
|
||||
$sql .= " ORDER BY ".$vrednost;
|
||||
}
|
||||
else {
|
||||
$sql .= " ORDER BY ".$orderPolje[$_POST['order'][0]['column']]." ".$_POST['order'][0]['dir'];
|
||||
}
|
||||
}
|
||||
|
||||
$vrednost='u.gdpr_agree desc';
|
||||
if($_POST['order'][0]['dir'] == 'asc'){
|
||||
$vrednost= ' FIELD (u.gdpr_agree, 0, \'-1\', 1)';
|
||||
}
|
||||
if($_POST['length'] != '-1') {
|
||||
$sql .= " LIMIT ".$_POST['start'].", ".$_POST['length'];
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY ".$vrednost;
|
||||
}else {
|
||||
$sql .= " ORDER BY ".$orderPolje[$_POST['order'][0]['column']]." ".$_POST['order'][0]['dir'];
|
||||
}
|
||||
}
|
||||
|
||||
if($_POST['length'] != '-1') {
|
||||
$sql .= " LIMIT ".$_POST['start'].", ".$_POST['length'];
|
||||
}
|
||||
|
||||
$resultQuery = sisplet_query($sql);
|
||||
$resultQuery = sisplet_query($sql);
|
||||
$resultU = lazyLoadSqlObj($resultQuery);
|
||||
|
||||
// Seznam uporabnikov vrne za administratorje vse za ostale pa samo tiste, ki smo jih dodali k uporabniku.
|
||||
if (!empty($resultU) && ($this->jeAdministrator() || !$this->jeAdministrator() && !empty($my) )) {
|
||||
// Seznam uporabnikov vrne za administratorje vse za ostale pa samo tiste, ki smo jih dodali k uporabniku.
|
||||
if (!empty($resultU)) {
|
||||
|
||||
if (!empty($resultU->name)) {
|
||||
$vsi[] = $resultU;
|
||||
} else {
|
||||
$vsi = $resultU;
|
||||
}
|
||||
if (!empty($resultU->name)) {
|
||||
$vsi[] = $resultU;
|
||||
}
|
||||
else {
|
||||
$vsi = $resultU;
|
||||
}
|
||||
|
||||
foreach ($vsi as $uporabnik) {
|
||||
$seznam[] = [
|
||||
iconv(mb_detect_encoding( $uporabnik->name, mb_detect_order(), true), "UTF-8", $uporabnik->name) .' '.iconv(mb_detect_encoding( $uporabnik->surname, mb_detect_order(), true), "UTF-8", $uporabnik->surname),
|
||||
(!empty($uporabnik->second_email) ? iconv(mb_detect_encoding( $uporabnik->second_email, mb_detect_order(), true), "UTF-8", $uporabnik->second_email) : iconv(mb_detect_encoding( $uporabnik->email, mb_detect_order(), true), "UTF-8", $uporabnik->email)),
|
||||
$this->userTypeToText($uporabnik->type),
|
||||
$admin_languages[$uporabnik->lang],
|
||||
(!empty($uporabnik->aai) ? $this->vrniDaNe($uporabnik->aai) : $lang['no1']),
|
||||
(!empty($uporabnik->st_anket) ? $uporabnik->st_anket : 0),
|
||||
(!empty($uporabnik->st_arhivskih) ? $uporabnik->st_arhivskih : 0),
|
||||
$lang["users_gdpr".$uporabnik->gdpr_agree],
|
||||
$uporabnik->registriran,
|
||||
$uporabnik->last_login,
|
||||
'<a href="#" onclick="edit_user(\''.$uporabnik->id.'\'); return false;" title="'.$lang['srv_info_modify'].'"><i class="fa fa-pencil-alt link-sv-moder"></i></a>'.
|
||||
' | <a href="#" onclick="vsiUporabnikiAkcija(\''.$uporabnik->id.'\', \'ban\'); return false;" title="'.$lang[($uporabnik->status == 0 ? 'srv_user_banned' : 'srv_user_notbanned')].'"><i class="fa fa-ban '.($uporabnik->status == 0 ? 'link-rdec' : 'link-sv-moder').'"></i></a>'.
|
||||
' | <a href="#" onclick="vsiUporabnikiAkcija(\''.$uporabnik->id.'\', \'delete\'); return false;" title="'.$lang['srv_multicrosstabs_tables_delete_short'].'"><i class="fa fa-times link-sv-moder"></i></a>'
|
||||
];
|
||||
foreach ($vsi as $uporabnik) {
|
||||
$seznam[] = [
|
||||
iconv(mb_detect_encoding( $uporabnik->name, mb_detect_order(), true), "UTF-8", $uporabnik->name) .' '.iconv(mb_detect_encoding( $uporabnik->surname, mb_detect_order(), true), "UTF-8", $uporabnik->surname),
|
||||
(!empty($uporabnik->second_email) ? iconv(mb_detect_encoding( $uporabnik->second_email, mb_detect_order(), true), "UTF-8", $uporabnik->second_email) : iconv(mb_detect_encoding( $uporabnik->email, mb_detect_order(), true), "UTF-8", $uporabnik->email)),
|
||||
$this->userTypeToText($uporabnik->type),
|
||||
$admin_languages[$uporabnik->lang],
|
||||
(!empty($uporabnik->aai) ? $this->vrniDaNe($uporabnik->aai) : $lang['no1']),
|
||||
(!empty($uporabnik->st_anket) ? $uporabnik->st_anket : 0),
|
||||
(!empty($uporabnik->st_arhivskih) ? $uporabnik->st_arhivskih : 0),
|
||||
$lang["users_gdpr".$uporabnik->gdpr_agree],
|
||||
$uporabnik->registriran,
|
||||
$uporabnik->last_login,
|
||||
'<a href="#" onclick="edit_user(\''.$uporabnik->id.'\'); return false;" title="'.$lang['srv_info_modify'].'"><i class="fa fa-pencil-alt link-sv-moder"></i></a>'.
|
||||
' | <a href="#" onclick="vsiUporabnikiAkcija(\''.$uporabnik->id.'\', \'ban\'); return false;" title="'.$lang[($uporabnik->status == 0 ? 'srv_user_banned' : 'srv_user_notbanned')].'"><i class="fa fa-ban '.($uporabnik->status == 0 ? 'link-rdec' : 'link-sv-moder').'"></i></a>'.
|
||||
' | <a href="#" onclick="vsiUporabnikiAkcija(\''.$uporabnik->id.'\', \'delete\'); return false;" title="'.$lang['srv_multicrosstabs_tables_delete_short'].'"><i class="fa fa-times link-sv-moder"></i></a>'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
$sql_recordsTotal = sisplet_query("SELECT count(id) as stVseh FROM users WHERE email NOT LIKE ('D3LMD-%') AND email NOT LIKE ('UNSU8MD-%')", "obj");
|
||||
|
||||
// Število vseh zadetkov, ki jih imamo v bazi
|
||||
$recordsTotal = 0;
|
||||
if(!empty($sql_recordsTotal)) {
|
||||
$recordsTotal = $sql_recordsTotal->stVseh;
|
||||
}
|
||||
|
||||
$sql_recordsTotal = sisplet_query("SELECT count(id) as stVseh FROM users WHERE email NOT LIKE ('D3LMD-%') AND email NOT LIKE ('UNSU8MD-%')", "obj");
|
||||
// Število vseh zadetkov, ki jih imamo v bazi
|
||||
$recordsTotal = 0;
|
||||
if(!empty($sql_recordsTotal) && is_null($my)) {
|
||||
$recordsTotal = $sql_recordsTotal->stVseh;
|
||||
} elseif(!is_null($my)) {
|
||||
$recordsTotal = sizeof($vsi);
|
||||
}
|
||||
|
||||
// Število filtriranih zadetkov
|
||||
$recordFiltered = $recordsTotal;
|
||||
if(!empty($_POST['search']['value']))
|
||||
$recordFiltered = sizeof($vsi);
|
||||
// Število filtriranih zadetkov
|
||||
$recordFiltered = $recordsTotal;
|
||||
if(!empty($_POST['search']['value']))
|
||||
$recordFiltered = sizeof($vsi);
|
||||
|
||||
echo json_encode([
|
||||
"draw" => (!empty($_POST['draw']) ? $_POST['draw'] : 1),
|
||||
@ -1164,7 +1161,126 @@ class Dostop {
|
||||
"recordsFiltered" => $recordFiltered,
|
||||
"data" => $seznam // polje z vsebino
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seznam dodeljenih uporabnikov (manager in admin)
|
||||
*/
|
||||
function ajax_all_users_list_my(){
|
||||
global $admin_languages;
|
||||
global $global_user_id;
|
||||
global $lang;
|
||||
global $admin_type;
|
||||
|
||||
$seznam = [];
|
||||
|
||||
$iskanjeSql = "";
|
||||
if(!empty($_POST['search']['value'])){
|
||||
$iskaniNiz = $_POST['search']['value'];
|
||||
$iskanjeSql = " AND (u.name LIKE '%".$iskaniNiz."%' OR u.surname LIKE '%".$iskaniNiz."%' OR u.email LIKE '%".$iskaniNiz."%' OR d1.dostop_survey_count LIKE '%".$iskaniNiz."%' OR d2.dostop_survey_archive LIKE '%".$iskaniNiz."%')";
|
||||
}
|
||||
|
||||
// Pridobimo vse uporabnike
|
||||
$sql = "SELECT u.id as id, u.type as type, u.status, u.email as email, u.name as name, u.surname as surname, u.lang as lang, u.eduroam as aai, date_format(u.when_reg, '%d.%m.%Y') as registriran, u.gdpr_agree as gdpr_agree, d1.dostop_survey_count as st_anket, d2.dostop_survey_archive as st_arhivskih, date_format(u.last_login, '%d.%m.%Y') as last_login, ue.email as second_email FROM users AS u ".
|
||||
" LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_count FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup='0' GROUP BY srv_dostop.uid ) AS d1 ON d1.uid = u.id ".
|
||||
" LEFT OUTER JOIN ( SELECT srv_dostop.ank_id, srv_dostop.uid, count(*) AS dostop_survey_archive FROM srv_dostop, srv_anketa WHERE srv_anketa.id=srv_dostop.ank_id AND srv_anketa.backup>'0' GROUP BY srv_dostop.uid ) AS d2 ON d2.uid = u.id ".
|
||||
" LEFT OUTER JOIN (SELECT user_emails.email, user_emails.user_id FROM user_emails WHERE active=1) AS ue ON ue.user_id = u.id".
|
||||
" WHERE u.email NOT LIKE ('D3LMD-%') AND u.email NOT LIKE ('UNSU8MD-%') ".$iskanjeSql;
|
||||
|
||||
// Filter samo po lastnih uporabnikih
|
||||
$isciPoDomeni = '';
|
||||
|
||||
// Med lastne uporabnike prikažemo tudi, tiste ki so bili registrirani z isto domeno
|
||||
/*UserSetting :: getInstance()->Init($global_user_id);
|
||||
$domena = UserSetting :: getInstance()->getUserSetting('manage_domain');
|
||||
if(!empty($domena)){
|
||||
$isciPoDomeni = " OR u.email LIKE '%".$domena."'";
|
||||
}*/
|
||||
|
||||
$sql .= " AND (u.id IN (SELECT user FROM srv_dostop_manage WHERE manager='".$global_user_id."') ".$isciPoDomeni.")";
|
||||
|
||||
|
||||
// Filtri, ki jih datatables pošilja in po katerih filtriramo
|
||||
if($_POST['order'][0]['column'] < 10) {
|
||||
$orderPolje = [
|
||||
"u.name ".$_POST['order'][0]['dir'].", u.surname",
|
||||
"u.email",
|
||||
"u.type",
|
||||
"u.lang",
|
||||
"u.eduroam", //AAI
|
||||
"d1.dostop_survey_count", //st_anket
|
||||
"d2.dostop_survey_archive", //st_arhivskih
|
||||
"u.gdpr_agree",
|
||||
"u.when_reg",
|
||||
"u.last_login"
|
||||
];
|
||||
|
||||
if($_POST['order'][0]['column'] == 7){
|
||||
|
||||
$vrednost='u.gdpr_agree desc';
|
||||
if($_POST['order'][0]['dir'] == 'asc'){
|
||||
$vrednost= ' FIELD (u.gdpr_agree, 0, \'-1\', 1)';
|
||||
}
|
||||
|
||||
$sql .= " ORDER BY ".$vrednost;
|
||||
}
|
||||
else {
|
||||
$sql .= " ORDER BY ".$orderPolje[$_POST['order'][0]['column']]." ".$_POST['order'][0]['dir'];
|
||||
}
|
||||
}
|
||||
|
||||
if($_POST['length'] != '-1') {
|
||||
$sql .= " LIMIT ".$_POST['start'].", ".$_POST['length'];
|
||||
}
|
||||
|
||||
$resultQuery = sisplet_query($sql);
|
||||
$resultU = lazyLoadSqlObj($resultQuery);
|
||||
|
||||
// Seznam uporabnikov vrne za administratorje vse za ostale pa samo tiste, ki smo jih dodali k uporabniku.
|
||||
if (!empty($resultU) && ($this->jeAdministrator() || !$this->jeAdministrator())) {
|
||||
|
||||
if (!empty($resultU->name)) {
|
||||
$vsi[] = $resultU;
|
||||
}
|
||||
else {
|
||||
$vsi = $resultU;
|
||||
}
|
||||
|
||||
foreach ($vsi as $uporabnik) {
|
||||
$seznam[] = [
|
||||
iconv(mb_detect_encoding( $uporabnik->name, mb_detect_order(), true), "UTF-8", $uporabnik->name) .' '.iconv(mb_detect_encoding( $uporabnik->surname, mb_detect_order(), true), "UTF-8", $uporabnik->surname),
|
||||
(!empty($uporabnik->second_email) ? iconv(mb_detect_encoding( $uporabnik->second_email, mb_detect_order(), true), "UTF-8", $uporabnik->second_email) : iconv(mb_detect_encoding( $uporabnik->email, mb_detect_order(), true), "UTF-8", $uporabnik->email)),
|
||||
$this->userTypeToText($uporabnik->type),
|
||||
$admin_languages[$uporabnik->lang],
|
||||
(!empty($uporabnik->aai) ? $this->vrniDaNe($uporabnik->aai) : $lang['no1']),
|
||||
(!empty($uporabnik->st_anket) ? $uporabnik->st_anket : 0),
|
||||
(!empty($uporabnik->st_arhivskih) ? $uporabnik->st_arhivskih : 0),
|
||||
$lang["users_gdpr".$uporabnik->gdpr_agree],
|
||||
$uporabnik->registriran,
|
||||
$uporabnik->last_login,
|
||||
'<a href="#" onclick="edit_user(\''.$uporabnik->id.'\'); return false;" title="'.$lang['srv_info_modify'].'"><i class="fa fa-pencil-alt link-sv-moder"></i></a>'.
|
||||
' | <a href="#" onclick="vsiUporabnikiAkcija(\''.$uporabnik->id.'\', \'ban\'); return false;" title="'.$lang[($uporabnik->status == 0 ? 'srv_user_banned' : 'srv_user_notbanned')].'"><i class="fa fa-ban '.($uporabnik->status == 0 ? 'link-rdec' : 'link-sv-moder').'"></i></a>'.
|
||||
' | <a href="#" onclick="vsiUporabnikiAkcija(\''.$uporabnik->id.'\', \'delete\'); return false;" title="'.$lang['srv_multicrosstabs_tables_delete_short'].'"><i class="fa fa-times link-sv-moder"></i></a>'
|
||||
];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Število vseh zadetkov, ki jih imamo v bazi
|
||||
$recordsTotal = 0;
|
||||
$recordsTotal = sizeof($vsi);
|
||||
|
||||
// Število filtriranih zadetkov
|
||||
$recordFiltered = $recordsTotal;
|
||||
if(!empty($_POST['search']['value']))
|
||||
$recordFiltered = sizeof($vsi);
|
||||
|
||||
echo json_encode([
|
||||
"draw" => (!empty($_POST['draw']) ? $_POST['draw'] : 1),
|
||||
"recordsTotal" => $recordsTotal,
|
||||
"recordsFiltered" => $recordFiltered,
|
||||
"data" => $seznam // polje z vsebino
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1238,7 +1354,8 @@ class Dostop {
|
||||
$type = $lang['admin_manager'];
|
||||
break;
|
||||
case 2:
|
||||
$type = $lang['admin_clan'];
|
||||
case 3:
|
||||
$type = $lang['admin_narocnik'];
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1315,15 +1432,13 @@ class Dostop {
|
||||
|
||||
public function ajax_unconfirmed_mail_user_list_delet_user()
|
||||
{
|
||||
global $user_db;
|
||||
|
||||
$uid = (!empty($_POST['uid']) ? $_POST['uid'] : NULL);
|
||||
|
||||
if (empty($uid)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sisplet_query("DELETE FROM $user_db.users_to_be WHERE id='" . $uid . "'");
|
||||
sisplet_query("DELETE FROM users_to_be WHERE id='" . $uid . "'");
|
||||
|
||||
echo 'ok';
|
||||
}
|
||||
@ -1331,7 +1446,6 @@ class Dostop {
|
||||
public function ajax_confirm_user_email()
|
||||
{
|
||||
global $pass_salt;
|
||||
global $user_db;
|
||||
|
||||
$uid = (!empty($_POST['uid']) ? $_POST['uid'] : NULL);
|
||||
|
||||
@ -1340,15 +1454,15 @@ class Dostop {
|
||||
}
|
||||
|
||||
// kopirano iz user_to_be v users
|
||||
$result = sisplet_query("SELECT type, email, name, surname, pass, status, gdpr_agree, when_reg, came_from, lang FROM " . $user_db . "users_to_be WHERE id='" . $uid . "'");
|
||||
$result = sisplet_query("SELECT type, email, name, surname, pass, status, gdpr_agree, when_reg, came_from, lang FROM users_to_be WHERE id='" . $uid . "'");
|
||||
|
||||
if (mysqli_num_rows($result) > 0) {
|
||||
$r = mysqli_fetch_assoc($result);
|
||||
$g = base64_encode((hash('SHA256', base64_decode($r['pass']) . $pass_salt)));
|
||||
|
||||
sisplet_query("INSERT INTO $user_db.users (type, email, name, surname, pass, status, gdpr_agree, when_reg, came_from, lang, manuallyApproved)
|
||||
sisplet_query("INSERT INTO users (type, email, name, surname, pass, status, gdpr_agree, when_reg, came_from, lang, manuallyApproved)
|
||||
VALUES ('" . $r['type'] . "', '" . $r['email'] . "', '" . $r['name'] . "', '" . $r['surname'] . "', '" . $g . "','" . $r['status'] . "', '" . $r['gdpr_agree'] . "','" . $r['when_reg'] . "', '" . $r['came_from'] . "', '" . $r['lang'] . "', 'Y')");
|
||||
sisplet_query("DELETE FROM $user_db.users_to_be WHERE id='" . $uid . "' OR email='" . $r['email'] . "'");
|
||||
sisplet_query("DELETE FROM users_to_be WHERE id='" . $uid . "' OR email='" . $r['email'] . "'");
|
||||
|
||||
echo 'ok';
|
||||
} else {
|
||||
|
@ -118,7 +118,6 @@ class Forum {
|
||||
global $admin_type;
|
||||
global $pass_salt;
|
||||
global $global_user_id;
|
||||
global $user_db;
|
||||
global $cookie_domain;
|
||||
|
||||
// preden naredimo karkoli, odstranimo javascript iz vsebine in naslova:
|
||||
@ -142,7 +141,7 @@ class Forum {
|
||||
|
||||
if ($global_user_id > 0) {
|
||||
$uid = $global_user_id;
|
||||
$resu = sisplet_query ("SELECT name FROM $user_db.users WHERE id='" .$uid ."'");
|
||||
$resu = sisplet_query ("SELECT name FROM users WHERE id='" .$uid ."'");
|
||||
$ru = mysqli_fetch_row ($resu);
|
||||
$user = $ru[0];
|
||||
} else {
|
||||
@ -194,7 +193,7 @@ class Forum {
|
||||
|
||||
if ($_POST['alertmail'] != '') {
|
||||
$mail = $_POST['alertmail'];
|
||||
$sqla = sisplet_query("SELECT id FROM $user_db.users WHERE email = '$mail'");
|
||||
$sqla = sisplet_query("SELECT id FROM users WHERE email = '$mail'");
|
||||
|
||||
if (mysqli_num_rows($sqla) > 0) {
|
||||
$rowa = mysqli_fetch_row($sqla);
|
||||
@ -204,16 +203,16 @@ class Forum {
|
||||
// Preveri ali je vzdevek ze zaseden- ce je, mu dodaj neko stevilko da bo unique
|
||||
$a2 = $avtor;
|
||||
|
||||
$result = sisplet_query ("SELECT * FROM $user_db.users WHERE name='$a2' AND surname=''");
|
||||
$result = sisplet_query ("SELECT * FROM users WHERE name='$a2' AND surname=''");
|
||||
while (mysqli_num_rows ($result) > 0) {
|
||||
$a2 = $avtor .rand(0, 32767);
|
||||
$result = sisplet_query ("SELECT * FROM $user_db.users WHERE name='$a2' AND surname=''");
|
||||
$result = sisplet_query ("SELECT * FROM users WHERE name='$a2' AND surname=''");
|
||||
}
|
||||
|
||||
$avtor = $a2;
|
||||
$g = base64_encode((hash('SHA256', '' .$pass_salt)));
|
||||
|
||||
$sqln = sisplet_query("INSERT INTO $user_db.users (email, name, when_reg, came_from, pass) VALUES ('" .$_POST['alertmail'] ."', '$avtor', NOW(), '2', '$g')");
|
||||
$sqln = sisplet_query("INSERT INTO users (email, name, when_reg, came_from, pass) VALUES ('" .$_POST['alertmail'] ."', '$avtor', NOW(), '2', '$g')");
|
||||
$narocnikID = mysqli_insert_id($GLOBALS['connect_db']);
|
||||
|
||||
// Ker je noviregistriran mu dajmo se UID.
|
||||
@ -287,14 +286,14 @@ class Forum {
|
||||
|
||||
foreach ($mails as $key => $mail) {
|
||||
$mail = trim($mail);
|
||||
$sqla = sisplet_query("SELECT id FROM $user_db.users WHERE email = '$mail'");
|
||||
$sqla = sisplet_query("SELECT id FROM users WHERE email = '$mail'");
|
||||
|
||||
if (mysqli_num_rows($sqla) > 0) {
|
||||
$rowa = mysqli_fetch_row($sqla);
|
||||
$narocnikID = $rowa[0];
|
||||
} else {
|
||||
$g = base64_encode((hash('SHA256', '' .$pass_salt)));
|
||||
$sqln = sisplet_query("INSERT INTO $user_db.users (email, name, when_reg, camefrom, pass) VALUES ('$mail', '$mail', NOW(), '2', '$g')");
|
||||
$sqln = sisplet_query("INSERT INTO users (email, name, when_reg, camefrom, pass) VALUES ('$mail', '$mail', NOW(), '2', '$g')");
|
||||
$narocnikID = mysqli_insert_id($GLOBALS['connect_db']);
|
||||
}
|
||||
|
||||
@ -351,10 +350,9 @@ class Forum {
|
||||
global $global_user_id;
|
||||
global $admin_type;
|
||||
global $lang;
|
||||
global $user_db;
|
||||
|
||||
if (isset ($_GET['em'])) { // email iz alerta
|
||||
$result = sisplet_query ("SELECT id FROM $user_db.users WHERE email='" .$_GET['em'] ."'");
|
||||
$result = sisplet_query ("SELECT id FROM users WHERE email='" .$_GET['em'] ."'");
|
||||
$r = mysqli_fetch_row ($result);
|
||||
return $r[0];
|
||||
}
|
||||
@ -368,10 +366,9 @@ class Forum {
|
||||
global $lang;
|
||||
global $site_url;
|
||||
global $skin_name;
|
||||
global $user_db;
|
||||
|
||||
if ($uid > 0) {
|
||||
$sql = sisplet_query("SELECT email, name, show_email FROM $user_db.users WHERE id='$uid'");
|
||||
$sql = sisplet_query("SELECT email, name, show_email FROM users WHERE id='$uid'");
|
||||
$row = mysqli_fetch_row($sql);
|
||||
$return = '';
|
||||
|
||||
|
@ -884,10 +884,10 @@ class SurveyAktivnost{
|
||||
$filter .= " ((user_access.package_id='2' OR user_access.package_id='3') AND user_access.time_expire > NOW()) AND ";
|
||||
}
|
||||
if($package_2ka == 0){
|
||||
$filter .= " (user_access.package_id!='2' OR user_access.time_expire < NOW()) AND ";
|
||||
$filter .= " (user_access.package_id!='2' OR user_access.time_expire < NOW() OR user_access.package_id IS NULL) AND ";
|
||||
}
|
||||
if($package_3ka == 0){
|
||||
$filter .= " (user_access.package_id!='3' OR user_access.time_expire < NOW()) AND ";
|
||||
$filter .= " (user_access.package_id!='3' OR user_access.time_expire < NOW() OR user_access.package_id IS NULL) AND ";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,10 +198,12 @@ class SurveyAlert
|
||||
$MailFrom = Common::getInstance()->getFromEmail();
|
||||
$MailReply = Common::getInstance()->getReplyToEmail();
|
||||
if ($emails != "" && $text != "" && $subject != "" && self::$data['alert_date'] != "") {
|
||||
// izberemo bazo srvcrontab
|
||||
|
||||
// izberemo bazo srvcrontab
|
||||
$db = mysqli_select_db($GLOBALS['connect_db'],'surveycrontab');
|
||||
//or die($lang['srv_alert_database_error']);
|
||||
if ($db) {
|
||||
//or die($lang['srv_alert_database_error']);
|
||||
|
||||
if ($db) {
|
||||
# najprej pobrišemo stare vrendosti, ker se alerti niso spremenili ob trajni anketi
|
||||
$del = sisplet_query("DELETE FROM srv_alert WHERE sid='".self::getSurveyId()."'");
|
||||
// najprej preverimo ali imamo za obstojeco anketo se kaj v crontabu (status = 0) in popravimo na status = 2 (spremenjen)
|
||||
@ -215,24 +217,26 @@ class SurveyAlert
|
||||
$sqlInsertString = "INSERT INTO srv_alert (dbname, sid, emails, text, subject, send_date, status, MailFrom, MailReply) " .
|
||||
"VALUES ('".$oldDb."', '".self::getSurveyId()."', '".$emails."', '".$text."', '".$subject."', '".self::$data['alert_date']."', 0, '".$MailFrom."', '".$MailReply."')";
|
||||
$sqlInsert = sisplet_query($sqlInsertString);
|
||||
|
||||
// uporabimo spet staro bazo
|
||||
mysqli_select_db($GLOBALS['connect_db'],$oldDb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// uporabimo spet staro bazo
|
||||
mysqli_select_db($GLOBALS['connect_db'],$oldDb);
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
# ankata je deaktivirana, vse alerte ki so še aktivni spremenimo v status 3
|
||||
$db = mysqli_select_db($GLOBALS['connect_db'],'surveycrontab');
|
||||
if ($db) {
|
||||
|
||||
if ($db) {
|
||||
// or die($lang['srv_alert_database_error']);
|
||||
# nastavimo status na 3 - sprememba aktivnosti ankete
|
||||
$sqlUpdateOld = sisplet_query("UPDATE srv_alert SET status = 3 WHERE dbname = '".$oldDb."' AND sid = '".self::getSurveyId()."' AND status = 0");
|
||||
// uporabimo spet staro bazo
|
||||
mysqli_select_db($GLOBALS['connect_db'],$oldDb);
|
||||
}
|
||||
}
|
||||
|
||||
// uporabimo spet staro bazo
|
||||
mysqli_select_db($GLOBALS['connect_db'],$oldDb);
|
||||
}
|
||||
sisplet_query("COMMIT");
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ class SurveyList {
|
||||
* @desc prikaze zgornjo navigacijo
|
||||
*/
|
||||
function display_sub_tabs () {
|
||||
global $lang, $global_user_id, $admin_type;
|
||||
global $lang, $global_user_id, $admin_type, $site_domain;
|
||||
|
||||
$SLCount = $this->countSurveys();
|
||||
|
||||
@ -239,14 +239,26 @@ class SurveyList {
|
||||
echo '<div id="secondNavigation" class="library clr">';
|
||||
|
||||
if ($_GET['a']=='diagnostics') {
|
||||
if ($_GET['t'] == 'uporabniki') {
|
||||
if ($admin_type == 0) {
|
||||
|
||||
if ($_GET['t'] == 'uporabniki') {
|
||||
|
||||
// Admini imajo pregled nad vsemi zavihki uporabnikov
|
||||
if ($admin_type == 0) {
|
||||
echo '<ul class="secondNavigation">';
|
||||
|
||||
#zavihek ankete - seznam vseh uporabnikov
|
||||
#zavihek osnovni pregled uporabnikov
|
||||
echo '<li>';
|
||||
echo '<a class="no-img single '.(in_array($_GET['m'], ['my', 'all']) ? 'active' : '').'"'
|
||||
.' href="index.php?a=diagnostics&t=uporabniki&m=my" title="'.$lang['n_users_list_all'].'">';
|
||||
echo '<a class="no-img single '.((!isset($_GET['m']) || $_GET['m'] == 'my') ? 'active' : '').'"'
|
||||
.' href="index.php?a=diagnostics&t=uporabniki" title="'.$lang['n_users_list_all'].'">';
|
||||
echo $lang['n_users_list'].'</a>';
|
||||
echo '</li>';
|
||||
|
||||
echo '<li class="space"></li>';
|
||||
|
||||
#zavihek seznam vseh uporabnikov
|
||||
echo '<li>';
|
||||
echo '<a class="no-img single '.($_GET['m'] == 'all' ? 'active' : '').'"'
|
||||
.' href="index.php?a=diagnostics&t=uporabniki&m=all" title="'.$lang['n_users_list_all'].'">';
|
||||
echo $lang['n_users_list_all'].'</a>';
|
||||
echo '</li>';
|
||||
|
||||
@ -286,12 +298,25 @@ class SurveyList {
|
||||
echo $lang['srv_hierarchy_users_access'].'</a>';
|
||||
echo '</li>';
|
||||
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
// Menegerji imajo samo osnovni pregled svojih uporabnikov
|
||||
if ($admin_type == 1) {
|
||||
|
||||
|
||||
echo '<ul class="secondNavigation">';
|
||||
|
||||
#zavihek osnovni pregled uporabnikov
|
||||
echo '<li>';
|
||||
echo '<a class="no-img single active" href="index.php?a=diagnostics&t=uporabniki" title="'.$lang['n_users_list_all'].'">';
|
||||
echo $lang['n_users_list'].'</a>';
|
||||
echo '</li>';
|
||||
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
|
||||
if ($admin_type == 0) {
|
||||
echo '<ul class="secondNavigation">';
|
||||
#zavihek ankete
|
||||
@ -439,11 +464,12 @@ class SurveyList {
|
||||
echo '<li class="space"></li>';
|
||||
|
||||
// Moj profil - preneseno iz sispleta (sispleta se ne bo uporabljalo vec)
|
||||
echo '<li>';
|
||||
echo '<a class="no-img side-right'.($tab=='global_user_myProfile' ? ' active' : '').'"'
|
||||
.' href="index.php?a=nastavitve&m=global_user_myProfile" title="'.$lang['edit_data'].'">';
|
||||
echo $lang['edit_data'].'</a>';
|
||||
echo '</li>';
|
||||
if($site_domain != '1ka.arnes.si') {
|
||||
echo '<li>';
|
||||
echo '<a class="no-img side-right' . ($tab == 'global_user_myProfile' ? ' active' : '') . '"' . ' href="index.php?a=nastavitve&m=global_user_myProfile" title="' . $lang['edit_data'] . '">';
|
||||
echo $lang['edit_data'] . '</a>';
|
||||
echo '</li>';
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
}
|
||||
@ -701,7 +727,7 @@ class SurveyList {
|
||||
# ni smiselno da ostali uporabniki vidijo zavihek, ker so tako prikazane samo njihove ankete
|
||||
echo '<li class="spaceBig"> </li>';
|
||||
echo '<li>';
|
||||
echo '<a href="index.php?a=diagnostics&t=uporabniki&m=my" title="' . $lang['hour_users'] . '">';
|
||||
echo '<a href="index.php?a=diagnostics&t=uporabniki" title="' . $lang['hour_users'] . '">';
|
||||
echo '<div class="smaller-singlebutton-'.$css_5.'">'. $lang['hour_users'] . '</div>';
|
||||
echo '</a>';
|
||||
echo '</li>';
|
||||
@ -3193,7 +3219,7 @@ class SurveyList {
|
||||
}
|
||||
|
||||
$sqlSurveyList = sisplet_query($stringSurveyList);
|
||||
list($count) = mysqli_fetch_row($sqlSurveyList);
|
||||
[$count] = mysqli_fetch_row($sqlSurveyList);
|
||||
|
||||
return (int)$count;
|
||||
}
|
||||
|
@ -3380,11 +3380,7 @@ class Vprasanje {
|
||||
echo '<option value="9"' . ($row['orientation'] == 9 ? ' selected="true"' : '') . '>'.$lang['srv_custom-picture_radio'].'</option>'; // Custom picture za radio tip
|
||||
echo '<option value="10"' . ($row['orientation'] == 10 ? ' selected="true"' : '') . '>'.$lang['srv_hot_spot'].'</option>'; //image hotspot
|
||||
echo '<option value="11"' . ($row['orientation'] == 11 ? ' selected="true"' : '') . '>'.$lang['srv_visual_analog_scale'].'</option>'; //vizualna analaogna skala - smeški
|
||||
if ($admin_type == 0){
|
||||
//echo '<option value="8"' . ($row['orientation'] == 8 ? ' selected="true"' : '') . '>'.$lang['srv_drag_drop'].'</option>';
|
||||
echo '<option value="5"' . ($row['hidden_default'] == 1 ? ' selected="true"' : '') . '>'.$lang['srv_potrditev'].'</option>';
|
||||
//echo '<option value="10"' . ($row['orientation'] == 10 ? ' selected="true"' : '') . '>'.$lang['srv_hot_spot'].'</option>'; //image hotspot
|
||||
}
|
||||
echo '<option value="5"' . ($row['hidden_default'] == 1 ? ' selected="true"' : '') . '>'.$lang['srv_potrditev'].'</option>';
|
||||
echo '</select></span>';
|
||||
echo '</p>';
|
||||
}
|
||||
|
@ -295,7 +295,7 @@
|
||||
define ('STR_DLMT', "|");
|
||||
define ('DAT_EXT', '.dat');
|
||||
define ('TMP_EXT', '.tmp');
|
||||
define ('PIPE_CHAR', "\x7C",true);
|
||||
define ('PIPE_CHAR', '\x7C');
|
||||
define ('STR_LESS_THEN', '\x3C');
|
||||
define ('STR_GREATER_THEN', '\x3E');
|
||||
define ('STR_EQUALS', '\x3D');
|
||||
|
@ -14,27 +14,27 @@ define("M_ANALIZA_SUMS", "sums");
|
||||
|
||||
/*PDF*/
|
||||
define("A_REPORT_VPRASALNIK_PDF", "vprasalnik_pdf");
|
||||
define("A_REPORT_PDF_RESULTS","pdf_results",true);
|
||||
define("A_REPORT_PDF_COMMENT","pdf_comment",true);
|
||||
define("A_REPORT_PDF_RESULTS","pdf_results");
|
||||
define("A_REPORT_PDF_COMMENT","pdf_comment");
|
||||
|
||||
define("M_REPORT_ANALIZA_PDF_FREKVENCA","frequency",true);
|
||||
define("M_REPORT_ANALIZA_PDF_CROSSTAB_IZPIS","crosstabs_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_MULTICROSSTAB_IZPIS","multicrosstabs_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_MEAN_IZPIS","mean_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_TTEST_IZPIS","ttest_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_BREAK_IZPIS","break_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_STAT","statistics",true);
|
||||
define("M_REPORT_ANALIZA_PDF_CHARTS","charts",true);
|
||||
define("M_REPORT_ANALIZA_PDF_SUMS","sums",true);
|
||||
define("M_REPORT_ANALIZA_PDF_CREPORT","creport_pdf",true);
|
||||
define("M_REPORT_ANALIZA_PDF_FREKVENCA","frequency");
|
||||
define("M_REPORT_ANALIZA_PDF_CROSSTAB_IZPIS","crosstabs_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_MULTICROSSTAB_IZPIS","multicrosstabs_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_MEAN_IZPIS","mean_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_TTEST_IZPIS","ttest_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_BREAK_IZPIS","break_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_STAT","statistics");
|
||||
define("M_REPORT_ANALIZA_PDF_CHARTS","charts");
|
||||
define("M_REPORT_ANALIZA_PDF_SUMS","sums");
|
||||
define("M_REPORT_ANALIZA_PDF_CREPORT","creport_pdf");
|
||||
|
||||
define("A_REPORT_PDF_STATUS","status",true);
|
||||
define("A_REPORT_PDF_EDITS_ANALYSIS","editsAnalysis",true);
|
||||
define("A_REPORT_PDF_LIST","list_pdf",true);
|
||||
define("M_REPORT_PDF_EVOLI","pdf_evoli",true);
|
||||
define("M_REPORT_PDF_TEAMMETER","pdf_teammeter",true);
|
||||
define("M_REPORT_PDF_MFDPS","pdf_mfpds",true);
|
||||
define("M_REPORT_PDF_HEATMAP_IMAGE","heatmap_image_pdf",true);
|
||||
define("A_REPORT_PDF_STATUS","status");
|
||||
define("A_REPORT_PDF_EDITS_ANALYSIS","editsAnalysis");
|
||||
define("A_REPORT_PDF_LIST","list_pdf");
|
||||
define("M_REPORT_PDF_EVOLI","pdf_evoli");
|
||||
define("M_REPORT_PDF_TEAMMETER","pdf_teammeter");
|
||||
define("M_REPORT_PDF_MFDPS","pdf_mfpds");
|
||||
define("M_REPORT_PDF_HEATMAP_IMAGE","heatmap_image_pdf");
|
||||
|
||||
define("M_REPORT_HIERARHIJA_PDF_IZPIS", "hierarhija_pdf_izpis");
|
||||
|
||||
@ -59,7 +59,7 @@ define("M_REPORT_ANALIZA_RTF_CHARTS", "charts_rtf");
|
||||
define("M_REPORT_ANALIZA_RTF_CREPORT", "creport_rtf");
|
||||
|
||||
define("A_REPORT_RTF_LIST", "list_rtf");
|
||||
define("M_REPORT_ANALIZA_RTF_HEATMAP_IMAGE","heatmap_image_rtf",true);
|
||||
define("M_REPORT_ANALIZA_RTF_HEATMAP_IMAGE","heatmap_image_rtf");
|
||||
|
||||
define("A_GDPR_RTF_INDIVIDUAL", "rtf_gdpr_individual");
|
||||
define("A_GDPR_RTF_ACTIVITY", "rtf_gdpr_activity");
|
||||
|
@ -111,7 +111,7 @@ define ("circleSlider", '\def\circleSLIDER#1#2{% 1: length, 2: position of the m
|
||||
\fill[rounded corners=0.1cm, draw=gray, fill=lightgray] (start) rectangle (end);
|
||||
\fill[draw=gray, rounded corners=0.2mm, fill=gray!20!gray] (mark) circle(.15) ;
|
||||
}
|
||||
}', true);
|
||||
}');
|
||||
|
||||
#definicija za izris drsnika brez kroglice
|
||||
define ("emptySlider", '\def\emptySLIDER#1{% 1: length
|
||||
@ -120,25 +120,16 @@ define ("emptySlider", '\def\emptySLIDER#1{% 1: length
|
||||
\coordinate (end) at (#1,0.1cm);
|
||||
\fill[rounded corners=0.1cm, draw=gray, fill=lightgray] (start) rectangle (end);
|
||||
}
|
||||
}', true);
|
||||
}');
|
||||
|
||||
#definicija latex kode za dodajanje skripte za generiranje xls iz html
|
||||
/* define ("headWithXlsScript",
|
||||
'\ifdefined\HCode
|
||||
\AtBeginDocument{%
|
||||
\Configure{@HEAD}{\HCode{<script src="./table2excel/dist/jquery.table2excel.js"></script>\Hnewline}}
|
||||
\ConfigureEnv{quote}{\Tg<quote>}{\Tg</quote>}{}{}
|
||||
}
|
||||
\fi',
|
||||
true); */
|
||||
define ("headWithXlsScript",
|
||||
'\ifdefined\HCode
|
||||
\AtBeginDocument{%
|
||||
\Configure{@HEAD}{\HCode{<script src="./export/script/saveAsExcel2.js"></script>\Hnewline}}
|
||||
\ConfigureEnv{quote}{\Tg<quote>}{\Tg</quote>}{}{}
|
||||
}
|
||||
\fi',
|
||||
true);
|
||||
\fi');
|
||||
|
||||
class LatexDocument{
|
||||
|
||||
|
@ -113,7 +113,7 @@
|
||||
if(isset($_GET['a']) && ($_GET['a'] == 'hierarhija_superadmin' || $_GET['a'] == 'hierarhija')){
|
||||
echo '<script type="text/javascript" src="minify/g=jshierarhija?v='.$rowv['value'].'"></script>';
|
||||
}
|
||||
elseif($_GET['a'] == 'narocila' || ($_GET['t'] == 'uporabniki' && in_array($_GET['m'], ['all', 'my', 'izbrisani', 'nepotrjeni', 'odjavljeni']))){
|
||||
elseif($_GET['a'] == 'narocila' || $_GET['t'] == 'uporabniki'){
|
||||
echo '<script type="text/javascript" src="minify/g=jsLastLib?v='.$rowv['value'].'"></script>';
|
||||
}
|
||||
else{
|
||||
|
@ -30,35 +30,35 @@ define("M_ANALIZA_SUMS", "sums");
|
||||
|
||||
/*PDF*/
|
||||
define("A_REPORT_VPRASALNIK_PDF", "vprasalnik_pdf");
|
||||
define("A_REPORT_PDF_RESULTS","pdf_results",true);
|
||||
define("A_REPORT_PDF_COMMENT","pdf_comment",true);
|
||||
define("M_REPORT_ANALIZA_PDF_FREKVENCA","frequency",true);
|
||||
define("M_REPORT_ANALIZA_PDF_CROSSTAB_IZPIS","crosstabs_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_MULTICROSSTAB_IZPIS","multicrosstabs_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_MEAN_IZPIS","mean_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_TTEST_IZPIS","ttest_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_BREAK_IZPIS","break_izpis",true);
|
||||
define("M_REPORT_ANALIZA_PDF_STAT","statistics",true);
|
||||
define("M_REPORT_ANALIZA_PDF_CHARTS","charts",true);
|
||||
define("M_REPORT_ANALIZA_PDF_SUMS","sums",true);
|
||||
define("M_REPORT_ANALIZA_PDF_CREPORT","creport_pdf",true);
|
||||
define("A_REPORT_PDF_STATUS","status",true);
|
||||
define("A_REPORT_PDF_EDITS_ANALYSIS","editsAnalysis",true);
|
||||
define("A_REPORT_PDF_LIST","list_pdf",true);
|
||||
define("M_REPORT_PDF_EVOLI","pdf_evoli",true);
|
||||
define("M_REPORT_PDF_TEAMMETER","pdf_teammeter",true);
|
||||
define("M_REPORT_PDF_EMPLOYMETER","pdf_employmeter",true);
|
||||
define("M_REPORT_PDF_MFDPS","pdf_mfpds",true);
|
||||
define("M_REPORT_PDF_MJU","pdf_mju",true);
|
||||
define("M_REPORT_PDF_MJU2","pdf_mju2",true);
|
||||
define("M_REPORT_BORZA","borza_chart",true);
|
||||
define("M_REPORT_PDF_HEATMAP_IMAGE","heatmap_image_pdf",true);
|
||||
define("A_REPORT_PDF_RESULTS","pdf_results");
|
||||
define("A_REPORT_PDF_COMMENT","pdf_comment");
|
||||
define("M_REPORT_ANALIZA_PDF_FREKVENCA","frequency");
|
||||
define("M_REPORT_ANALIZA_PDF_CROSSTAB_IZPIS","crosstabs_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_MULTICROSSTAB_IZPIS","multicrosstabs_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_MEAN_IZPIS","mean_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_TTEST_IZPIS","ttest_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_BREAK_IZPIS","break_izpis");
|
||||
define("M_REPORT_ANALIZA_PDF_STAT","statistics");
|
||||
define("M_REPORT_ANALIZA_PDF_CHARTS","charts");
|
||||
define("M_REPORT_ANALIZA_PDF_SUMS","sums");
|
||||
define("M_REPORT_ANALIZA_PDF_CREPORT","creport_pdf");
|
||||
define("A_REPORT_PDF_STATUS","status");
|
||||
define("A_REPORT_PDF_EDITS_ANALYSIS","editsAnalysis");
|
||||
define("A_REPORT_PDF_LIST","list_pdf");
|
||||
define("M_REPORT_PDF_EVOLI","pdf_evoli");
|
||||
define("M_REPORT_PDF_TEAMMETER","pdf_teammeter");
|
||||
define("M_REPORT_PDF_EMPLOYMETER","pdf_employmeter");
|
||||
define("M_REPORT_PDF_MFDPS","pdf_mfpds");
|
||||
define("M_REPORT_PDF_MJU","pdf_mju");
|
||||
define("M_REPORT_PDF_MJU2","pdf_mju2");
|
||||
define("M_REPORT_BORZA","borza_chart");
|
||||
define("M_REPORT_PDF_HEATMAP_IMAGE","heatmap_image_pdf");
|
||||
define("M_REPORT_HIERARHIJA_PDF_IZPIS", "hierarhija_pdf_izpis");
|
||||
|
||||
/*RTF*/
|
||||
define("A_REPORT_VPRASALNIK_RTF", "vprasalnik_rtf");
|
||||
define("A_REPORT_RTF_RESULTS", "rtf_results");
|
||||
define("A_REPORT_RTF_COMMENT","rtf_comment",true);
|
||||
define("A_REPORT_RTF_COMMENT","rtf_comment");
|
||||
define("M_REPORT_ANALIZA_RTF_FREKVENCA", "frequency_rtf");
|
||||
define("M_REPORT_ANALIZA_RTF_CROSSTAB_IZPIS", "crosstabs_izpis_rtf");
|
||||
define("M_REPORT_ANALIZA_RTF_MULTICROSSTAB_IZPIS", "multicrosstabs_izpis_rtf");
|
||||
@ -70,7 +70,7 @@ define("M_REPORT_ANALIZA_RTF_SUMS", "sums_rtf");
|
||||
define("M_REPORT_ANALIZA_RTF_CHARTS", "charts_rtf");
|
||||
define("M_REPORT_ANALIZA_RTF_CREPORT", "creport_rtf");
|
||||
define("A_REPORT_RTF_LIST", "list_rtf");
|
||||
define("M_REPORT_ANALIZA_RTF_HEATMAP_IMAGE","heatmap_image_rtf",true);
|
||||
define("M_REPORT_ANALIZA_RTF_HEATMAP_IMAGE","heatmap_image_rtf");
|
||||
|
||||
/*XLS*/
|
||||
define("M_REPORT_ANALIZA_XLS_STAT", "statistics_xls");
|
||||
@ -96,7 +96,7 @@ define("A_LANGUAGE_TECHNOLOGY_XLS", "lt_excel");
|
||||
|
||||
/*PPT*/
|
||||
define("M_REPORT_ANALIZA_PPT_CHARTS", "charts_ppt");
|
||||
define("M_REPORT_ANALIZA_PPT_HEATMAP_IMAGE","heatmap_image_ppt",true);
|
||||
define("M_REPORT_ANALIZA_PPT_HEATMAP_IMAGE","heatmap_image_ppt");
|
||||
|
||||
/*IMAGE*/
|
||||
define("M_REPORT_ANALIZA_HEATMAP_IMAGE", "heatmap_image");
|
||||
|
@ -183,9 +183,9 @@ class GC{
|
||||
'4_1' => 'predmeti'
|
||||
);
|
||||
|
||||
$reports_id = '08122020';
|
||||
$report_type = '2_2';
|
||||
$fak_id = '3000018';
|
||||
$reports_id = '11012021';
|
||||
$report_type = '1_1';
|
||||
$fak_id = '3000043';
|
||||
$zip_name = '';
|
||||
|
||||
// Nastavimo pot do pdf-jev
|
||||
@ -206,7 +206,7 @@ class GC{
|
||||
//$this->executeManualUpload($zip_name, $fak_id, $report_type, $reports_id, $unzip=false);
|
||||
|
||||
// BRANJE POROCIL - IZVAJALEC
|
||||
//$response = $this->readFolder($zadeva_id='RezultatiAnket_'.$fak_id.'_190', $fakultete[$fak_id]['kratica']);
|
||||
//$response = $this->readFolder($zadeva_id='RezultatiAnket_'.$fak_id.'_11', $fakultete[$fak_id]['kratica']);
|
||||
|
||||
// BRANJE POROCIL - FAKULTETA
|
||||
//$response = $this->readFolder($zadeva_id='RezultatiAnket_'.$fak_id.'_2019_2020', $fakultete[$fak_id]['kratica']);
|
||||
|
@ -19,7 +19,6 @@ global $global_user_id;
|
||||
global $mysql_database_name;
|
||||
global $pass_salt;
|
||||
global $is_meta;
|
||||
global $user_db;
|
||||
global $cookie_domain;
|
||||
global $lang;
|
||||
global $site_url;
|
||||
|
@ -282,57 +282,27 @@ $(document).ready(function () {
|
||||
}
|
||||
|
||||
if ($('#my_users_list').length > 0) {
|
||||
tabelaDataTables = $('#my_users_list').DataTable({
|
||||
"ajax": {
|
||||
"url": siteUrl+"admin/survey/ajax.php?t=dostop&a=my_users_list",
|
||||
"type": "post"
|
||||
},
|
||||
serverSide: true,
|
||||
lengthMenu: [[50, 500, 1000, 5000, 10000], [50, 500, 1000, 5000, 10000]],
|
||||
dom: 'Blfrtip',
|
||||
deferRender: true,
|
||||
select: true,
|
||||
buttons: [
|
||||
{
|
||||
extend: 'copy',
|
||||
exportOptions: {
|
||||
columns: ':visible'
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'print',
|
||||
exportOptions: {
|
||||
columns: ':visible'
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'csv',
|
||||
bom: true,
|
||||
exportOptions: {
|
||||
columns: ':visible'
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'excel',
|
||||
bom: true,
|
||||
exportOptions: {
|
||||
columns: ':visible'
|
||||
}
|
||||
},
|
||||
{
|
||||
extend: 'pdf',
|
||||
orientation: 'landscape',
|
||||
pageSize: 'LEGAL',
|
||||
exportOptions: {
|
||||
columns: ':visible'
|
||||
}
|
||||
},
|
||||
'colvis'
|
||||
],
|
||||
language: {
|
||||
"url": siteUrl+"admin/survey/script/datatables/Slovenian.json"
|
||||
}
|
||||
});
|
||||
tabelaDataTables = $('#my_users_list').DataTable({
|
||||
"ajax": {
|
||||
"url": siteUrl+"admin/survey/ajax.php?t=dostop&a=my_users_list",
|
||||
"type": "post"
|
||||
},
|
||||
serverSide: true,
|
||||
lengthMenu: [[50, 500, 1000, 5000, 10000], [50, 500, 1000, 5000, 10000]],
|
||||
dom: 'Blfrtip',
|
||||
deferRender: true,
|
||||
select: true,
|
||||
buttons: [
|
||||
],
|
||||
language: {
|
||||
"url": siteUrl+"admin/survey/script/datatables/Slovenian.json"
|
||||
},
|
||||
fnInitComplete : function() {
|
||||
if ($(this).find('tbody tr td').hasClass('dataTables_empty')) {
|
||||
$(this).parent().parent().hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if ($('#deleted_users_list').length > 0) {
|
||||
|
@ -1530,11 +1530,19 @@ function create_inv_editor (id, focus) {
|
||||
id='inv_message_body';
|
||||
|
||||
if (!editor_init) {
|
||||
CKEDITOR.replace( id );
|
||||
CKEDITOR.replace(id, {
|
||||
fullPage: true,
|
||||
allowedContent: true
|
||||
});
|
||||
|
||||
editor_init = true;
|
||||
}else{
|
||||
CKEDITOR.replace(id);
|
||||
}
|
||||
}
|
||||
else{
|
||||
CKEDITOR.replace(id, {
|
||||
fullPage: true,
|
||||
allowedContent: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function mailSourceMesageChange(what) {
|
||||
|
@ -3919,11 +3919,10 @@ function showSearchb() {
|
||||
|
||||
function executeDrupalSearch() {
|
||||
|
||||
//var url = 'https://www.1ka.si/d/sl/search/node/';
|
||||
var url = $('#drupal_search_url').val();
|
||||
var searchString = $('#searchSurvey').val();
|
||||
|
||||
window.location = url + encodeURIComponent(searchString);
|
||||
var searchString = $('#searchSurvey').val();
|
||||
|
||||
window.open(url + encodeURIComponent(searchString), '_blank');
|
||||
}
|
||||
|
||||
function showAdvancedSearch(){
|
||||
@ -4229,10 +4228,6 @@ function add_to_library(anketa,where) {
|
||||
$.post('ajax.php?a=add_to_library', {anketa:anketa, where:where});
|
||||
}
|
||||
|
||||
function refresh_user_diagnostic(field, type, show, limit) {
|
||||
$('#survey_list').load('ajax.php?a=refreshUserDiagnostic', {field:field, type:type, show:show, limit:limit});
|
||||
}
|
||||
|
||||
function create_archive_survey(anketa, msg) {
|
||||
$('#fade').fadeTo('slow', 1);
|
||||
$('#fullscreen').html('').fadeIn('slow').draggable({delay:100, cancel: 'input, textarea, select, .buttonwrapper'});
|
||||
|
111
composer.lock
generated
111
composer.lock
generated
@ -378,26 +378,26 @@
|
||||
},
|
||||
{
|
||||
"name": "maxmind-db/reader",
|
||||
"version": "v1.8.0",
|
||||
"version": "v1.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maxmind/MaxMind-DB-Reader-php.git",
|
||||
"reference": "b566d429ac9aec10594b0935be8ff38302f8d5c8"
|
||||
"reference": "9ee9ba9ee287b119e9f5a8e8dbfea0b49647cec4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/b566d429ac9aec10594b0935be8ff38302f8d5c8",
|
||||
"reference": "b566d429ac9aec10594b0935be8ff38302f8d5c8",
|
||||
"url": "https://api.github.com/repos/maxmind/MaxMind-DB-Reader-php/zipball/9ee9ba9ee287b119e9f5a8e8dbfea0b49647cec4",
|
||||
"reference": "9ee9ba9ee287b119e9f5a8e8dbfea0b49647cec4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2"
|
||||
},
|
||||
"conflict": {
|
||||
"ext-maxminddb": "<1.8.0,>=2.0.0"
|
||||
"ext-maxminddb": "<1.9.0,>=2.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.*",
|
||||
"friendsofphp/php-cs-fixer": "*",
|
||||
"php-coveralls/php-coveralls": "^2.1",
|
||||
"phpunit/phpcov": ">=6.0.0",
|
||||
"phpunit/phpunit": ">=8.0.0,<10.0.0",
|
||||
@ -434,7 +434,7 @@
|
||||
"geolocation",
|
||||
"maxmind"
|
||||
],
|
||||
"time": "2020-10-01 17:30:21"
|
||||
"time": "2021-01-07 21:15:29"
|
||||
},
|
||||
{
|
||||
"name": "maxmind/web-service-common",
|
||||
@ -751,6 +751,7 @@
|
||||
"homepage": "https://github.com/paypal/paypalhttp_php/contributors"
|
||||
}
|
||||
],
|
||||
"abandoned": true,
|
||||
"time": "2019-11-06 21:27:12"
|
||||
},
|
||||
{
|
||||
@ -1019,16 +1020,16 @@
|
||||
},
|
||||
{
|
||||
"name": "stripe/stripe-php",
|
||||
"version": "v7.66.1",
|
||||
"version": "v7.67.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/stripe/stripe-php.git",
|
||||
"reference": "a2ebaa272a8797b21e81afaf8d5ba0953ff15e13"
|
||||
"reference": "935d2c67912007f6d17b6c08a62050252c509129"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/a2ebaa272a8797b21e81afaf8d5ba0953ff15e13",
|
||||
"reference": "a2ebaa272a8797b21e81afaf8d5ba0953ff15e13",
|
||||
"url": "https://api.github.com/repos/stripe/stripe-php/zipball/935d2c67912007f6d17b6c08a62050252c509129",
|
||||
"reference": "935d2c67912007f6d17b6c08a62050252c509129",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1038,7 +1039,7 @@
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "2.16.5",
|
||||
"friendsofphp/php-cs-fixer": "2.17.1",
|
||||
"php-coveralls/php-coveralls": "^2.1",
|
||||
"phpunit/phpunit": "^5.7",
|
||||
"squizlabs/php_codesniffer": "^3.3",
|
||||
@ -1072,20 +1073,20 @@
|
||||
"payment processing",
|
||||
"stripe"
|
||||
],
|
||||
"time": "2020-12-01 18:44:12"
|
||||
"time": "2020-12-09 19:00:34"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-idn",
|
||||
"version": "v1.20.0",
|
||||
"version": "v1.22.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-idn.git",
|
||||
"reference": "3b75acd829741c768bc8b1f84eb33265e7cc5117"
|
||||
"reference": "0eb8293dbbcd6ef6bf81404c9ce7d95bcdf34f44"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/3b75acd829741c768bc8b1f84eb33265e7cc5117",
|
||||
"reference": "3b75acd829741c768bc8b1f84eb33265e7cc5117",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/0eb8293dbbcd6ef6bf81404c9ce7d95bcdf34f44",
|
||||
"reference": "0eb8293dbbcd6ef6bf81404c9ce7d95bcdf34f44",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1099,7 +1100,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.20-dev"
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1142,20 +1143,20 @@
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2020-10-23 14:02:19"
|
||||
"time": "2021-01-07 16:49:33"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-intl-normalizer",
|
||||
"version": "v1.20.0",
|
||||
"version": "v1.22.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
|
||||
"reference": "727d1096295d807c309fb01a851577302394c897"
|
||||
"reference": "6e971c891537eb617a00bb07a43d182a6915faba"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/727d1096295d807c309fb01a851577302394c897",
|
||||
"reference": "727d1096295d807c309fb01a851577302394c897",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/6e971c891537eb617a00bb07a43d182a6915faba",
|
||||
"reference": "6e971c891537eb617a00bb07a43d182a6915faba",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1167,7 +1168,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.20-dev"
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1209,20 +1210,20 @@
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2020-10-23 14:02:19"
|
||||
"time": "2021-01-07 17:09:11"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php72",
|
||||
"version": "v1.20.0",
|
||||
"version": "v1.22.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php72.git",
|
||||
"reference": "cede45fcdfabdd6043b3592e83678e42ec69e930"
|
||||
"reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cede45fcdfabdd6043b3592e83678e42ec69e930",
|
||||
"reference": "cede45fcdfabdd6043b3592e83678e42ec69e930",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
|
||||
"reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -1231,7 +1232,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.20-dev"
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -1268,7 +1269,7 @@
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2020-10-23 14:02:19"
|
||||
"time": "2021-01-07 16:49:33"
|
||||
},
|
||||
{
|
||||
"name": "web-token/jwt-core",
|
||||
@ -2022,25 +2023,25 @@
|
||||
},
|
||||
{
|
||||
"name": "maximebf/debugbar",
|
||||
"version": "v1.16.3",
|
||||
"version": "v1.16.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maximebf/php-debugbar.git",
|
||||
"reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372"
|
||||
"reference": "c86c717e4bf3c6d98422da5c38bfa7b0f494b04c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/1a1605b8e9bacb34cc0c6278206d699772e1d372",
|
||||
"reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372",
|
||||
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/c86c717e4bf3c6d98422da5c38bfa7b0f494b04c",
|
||||
"reference": "c86c717e4bf3c6d98422da5c38bfa7b0f494b04c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1",
|
||||
"php": "^7.1|^8",
|
||||
"psr/log": "^1.0",
|
||||
"symfony/var-dumper": "^2.6|^3|^4|^5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5"
|
||||
"phpunit/phpunit": "^7.5.20 || ^9.4.2"
|
||||
},
|
||||
"suggest": {
|
||||
"kriswallsmith/assetic": "The best way to manage assets",
|
||||
@ -2079,7 +2080,7 @@
|
||||
"debug",
|
||||
"debugbar"
|
||||
],
|
||||
"time": "2020-05-06 07:06:27"
|
||||
"time": "2020-12-07 10:48:48"
|
||||
},
|
||||
{
|
||||
"name": "psr/log",
|
||||
@ -2130,16 +2131,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-mbstring",
|
||||
"version": "v1.20.0",
|
||||
"version": "v1.22.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-mbstring.git",
|
||||
"reference": "39d483bdf39be819deabf04ec872eb0b2410b531"
|
||||
"reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/39d483bdf39be819deabf04ec872eb0b2410b531",
|
||||
"reference": "39d483bdf39be819deabf04ec872eb0b2410b531",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
|
||||
"reference": "f377a3dd1fde44d37b9831d68dc8dea3ffd28e13",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2151,7 +2152,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.20-dev"
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -2189,20 +2190,20 @@
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2020-10-23 14:02:19"
|
||||
"time": "2021-01-07 16:49:33"
|
||||
},
|
||||
{
|
||||
"name": "symfony/polyfill-php80",
|
||||
"version": "v1.20.0",
|
||||
"version": "v1.22.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/polyfill-php80.git",
|
||||
"reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de"
|
||||
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/e70aa8b064c5b72d3df2abd5ab1e90464ad009de",
|
||||
"reference": "e70aa8b064c5b72d3df2abd5ab1e90464ad009de",
|
||||
"url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/dc3063ba22c2a1fd2f45ed856374d79114998f91",
|
||||
"reference": "dc3063ba22c2a1fd2f45ed856374d79114998f91",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2211,7 +2212,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "1.20-dev"
|
||||
"dev-main": "1.22-dev"
|
||||
},
|
||||
"thanks": {
|
||||
"name": "symfony/polyfill",
|
||||
@ -2255,20 +2256,20 @@
|
||||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"time": "2020-10-23 14:02:19"
|
||||
"time": "2021-01-07 16:49:33"
|
||||
},
|
||||
{
|
||||
"name": "symfony/var-dumper",
|
||||
"version": "v4.4.17",
|
||||
"version": "v4.4.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/var-dumper.git",
|
||||
"reference": "65c6f1e848cda840ef7278686c8e30a7cc353c93"
|
||||
"reference": "4f31364bbc8177f2a6dbc125ac3851634ebe2a03"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/65c6f1e848cda840ef7278686c8e30a7cc353c93",
|
||||
"reference": "65c6f1e848cda840ef7278686c8e30a7cc353c93",
|
||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/4f31364bbc8177f2a6dbc125ac3851634ebe2a03",
|
||||
"reference": "4f31364bbc8177f2a6dbc125ac3851634ebe2a03",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@ -2327,7 +2328,7 @@
|
||||
"debug",
|
||||
"dump"
|
||||
],
|
||||
"time": "2020-11-24 09:55:37"
|
||||
"time": "2020-12-08 16:59:59"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
@ -93,6 +93,9 @@ CKEDITOR.editorConfig = function (config) {
|
||||
};
|
||||
config.disallowedContent = 'h1, h2, h3, h4, h5, h6';
|
||||
|
||||
// Full page mode (allow html, body...)
|
||||
//config.fullPage = true;
|
||||
|
||||
//DEV TOOLS
|
||||
//config.extraPlugins = 'devtools';
|
||||
|
||||
|
@ -422,8 +422,10 @@ class ApiLogin
|
||||
// Ce imamo vklopljeno blokiranje dostopa do admina glede na ip
|
||||
if(isset($app_settings['admin_allow_only_ip']) && $app_settings['admin_allow_only_ip'] != '' && !empty($app_settings['admin_allow_only_ip'])){
|
||||
|
||||
$ip = $_SERVER['REMOTE_ADDR'];
|
||||
|
||||
// Preverimo ip - ce se ne ujema ne pustimo logina
|
||||
if(!in_array($_SERVER['REMOTE_ADDR'], $app_settings['admin_allow_only_ip'])){
|
||||
if(!in_array($ip, $app_settings['admin_allow_only_ip'])){
|
||||
header('location: '.$this->page_urls['page_login'.$this->prijava]);
|
||||
die();
|
||||
}
|
||||
@ -1014,13 +1016,6 @@ class ApiLogin
|
||||
setcookie("SL", $p, time() - 3600 * 24 * 365, "/", $nd);
|
||||
}
|
||||
|
||||
// Ce gre za AAI odjavo moramo odjavit tudi iz AAI
|
||||
if (isset($_COOKIE['aai']) && !empty ($_COOKIE['aai']) && $_COOKIE['aai'] == "1") {
|
||||
setcookie("aai", '', time() - 3600, '/', $cookie_domain);
|
||||
header('location: https://aai.1ka.si/Shibboleth.sso/Logout?return=https://1ka.arnes.si');
|
||||
die();
|
||||
}
|
||||
|
||||
// Ce gre za arnes aai odjavo odjavimo posebej
|
||||
if ($aai_instalacija){
|
||||
setcookie("aai", '', time() - 3600, '/', $cookie_domain);
|
||||
@ -1601,7 +1596,6 @@ class ApiLogin
|
||||
global $site_path;
|
||||
global $lang;
|
||||
global $global_user_id;
|
||||
global $user_db;
|
||||
global $cookie_domain;
|
||||
global $app_settings;
|
||||
|
||||
@ -1611,7 +1605,7 @@ class ApiLogin
|
||||
$email = strtolower($_GET['email']);
|
||||
|
||||
if (is_numeric($email)) {
|
||||
$result = sisplet_query("SELECT email FROM $user_db.users WHERE id='$email'");
|
||||
$result = sisplet_query("SELECT email FROM users WHERE id='$email'");
|
||||
$r = mysqli_fetch_row($result);
|
||||
|
||||
$email = $r[0];
|
||||
@ -1622,7 +1616,7 @@ class ApiLogin
|
||||
list ($ByeEmail) = mysqli_fetch_row($result);
|
||||
$result = sisplet_query("SELECT value FROM misc WHERE what='ByeEmailSubject'");
|
||||
list ($ByeEmailSubject) = mysqli_fetch_row($result);
|
||||
$result = sisplet_query("SELECT name FROM $user_db.users WHERE email='$email'");
|
||||
$result = sisplet_query("SELECT name FROM users WHERE email='$email'");
|
||||
list ($ime) = mysqli_fetch_row($result);
|
||||
|
||||
$PageName = $app_settings['app_name'];
|
||||
@ -1645,7 +1639,7 @@ class ApiLogin
|
||||
}
|
||||
|
||||
|
||||
$result = sisplet_query("UPDATE $user_db.users SET email=CONCAT('UNSU8MD-', UNIX_TIMESTAMP(), email) WHERE email='$email'");
|
||||
$result = sisplet_query("UPDATE users SET email=CONCAT('UNSU8MD-', UNIX_TIMESTAMP(), email) WHERE email='$email'");
|
||||
setcookie('uid', '', time() - 3600, '/', $cookie_domain);
|
||||
setcookie('secret', '', time() - 3600, '/', $cookie_domain);
|
||||
|
||||
@ -1841,7 +1835,6 @@ class ApiLogin
|
||||
global $lang;
|
||||
global $site_url;
|
||||
global $pass_salt;
|
||||
global $user_db;
|
||||
global $cookie_domain;
|
||||
|
||||
$ajaxKlic = (!empty($_POST['ajax']) ? true : false);
|
||||
|
@ -0,0 +1,5 @@
|
||||
# Code of Conduct
|
||||
|
||||
Facebook has adopted a Code of Conduct that we expect project participants to adhere to.
|
||||
Please read the [full text](https://code.fb.com/codeofconduct/)
|
||||
so that you can understand what actions will and will not be tolerated.
|
@ -0,0 +1,35 @@
|
||||
# Contributing to Official Facebook Pixel
|
||||
We want to make contributing to this project as easy and transparent as
|
||||
possible.
|
||||
|
||||
## Pull Requests
|
||||
We actively welcome your pull requests.
|
||||
|
||||
1. Fork the repo and create your branch from `master`.
|
||||
2. If you've added code that should be tested, add tests.
|
||||
3. If you've changed APIs, update the documentation.
|
||||
4. Make sure your code lints.
|
||||
5. If you haven't already, complete the Contributor License Agreement ("CLA").
|
||||
|
||||
## Contributor License Agreement ("CLA")
|
||||
In order to accept your pull request, we need you to submit a CLA. You only need
|
||||
to do this once to work on any of Facebook's open source projects.
|
||||
|
||||
Complete your CLA here: <https://code.facebook.com/cla>
|
||||
|
||||
## Issues
|
||||
We use GitHub issues to track public bugs. Please ensure your description is
|
||||
clear and has sufficient instructions to be able to reproduce the issue.
|
||||
|
||||
Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
|
||||
disclosure of security bugs. In those cases, please go through the process
|
||||
outlined on that page and do not file a public issue.
|
||||
|
||||
## Coding Style
|
||||
* 4 spaces for indentation rather than tabs
|
||||
* 80 character line length
|
||||
|
||||
## License
|
||||
By contributing to Official Facebook Pixel, you agree that your contributions
|
||||
will be licensed under the LICENSE file in the root directory of
|
||||
this source tree.
|
339
frontend/drupal/modules/official_facebook_pixel/LICENSE
Normal file
339
frontend/drupal/modules/official_facebook_pixel/LICENSE
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
19
frontend/drupal/modules/official_facebook_pixel/README.md
Normal file
19
frontend/drupal/modules/official_facebook_pixel/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
# Official Facebook Pixel
|
||||
|
||||
Grow your business with Official Facebook Pixel! This plugin will
|
||||
install a Facebook Pixel on your Drupal site, detect and fire pixel events automatically!
|
||||
|
||||
## Get started
|
||||
|
||||
Download the zip file marked 'official-facebook-pixel-7.x-[version number].zip' attached to the current release.
|
||||
|
||||
## Requirements
|
||||
|
||||
Official Facebook Pixel requires
|
||||
* Drupal 7.x
|
||||
* PHP 5.6 or greater
|
||||
|
||||
## License
|
||||
|
||||
Official Facebook Pixel is GPLv2-licensed.
|
53
frontend/drupal/modules/official_facebook_pixel/README.txt
Normal file
53
frontend/drupal/modules/official_facebook_pixel/README.txt
Normal file
@ -0,0 +1,53 @@
|
||||
CONTENTS OF THIS FILE
|
||||
---------------------
|
||||
|
||||
* Introduction
|
||||
* Requirements
|
||||
* Installation
|
||||
* FAQ
|
||||
* Maintainers
|
||||
|
||||
|
||||
INTRODUCTION
|
||||
------------
|
||||
|
||||
This plugin will install a Facebook Pixel on your Drupal page. The Official Facebook Pixel allows
|
||||
you to fire PageView events when people visit your website. Tracking pixel events can help you
|
||||
understand the actions people are taking on your website. You can then use this information to
|
||||
make adjustments accordingly in your advertising campaigns.
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
------------
|
||||
* Drupal 7.x
|
||||
* PHP 5.6 or greater
|
||||
|
||||
INSTALLATION
|
||||
------------
|
||||
|
||||
1. Download the zip file attached to the current release.
|
||||
2. Go to your Drupal 7.x site, sign in and enter the "Modules" tab.
|
||||
3. Click "+ Install new module" and choose the zip file.
|
||||
4. Enable the "Official Facebook Pixel" module by check the checkbox and click "Save configuration".
|
||||
5. Go to the "Configuration" tab and click the "Official Facebook Pixel Settings".
|
||||
6. Paste your Facebook pixel ID into the text input box and click "Save configuration".
|
||||
|
||||
|
||||
FAQ
|
||||
---
|
||||
|
||||
Q: Where can I find more information about Facebook Pixel?
|
||||
A: https://www.facebook.com/business/learn/facebook-ads-pixel
|
||||
|
||||
Q: Where can I find more information about Official Facebook Pixel module?
|
||||
A: https://www.facebook.com/business/help/1946768672286771
|
||||
|
||||
Q: I am a developer. Can I help improve the module?
|
||||
A: Of course! This module is an open source project on GitHub. You can find the code and contribution instructions in: https://github.com/facebookincubator/Facebook-Pixel-for-Drupal.
|
||||
|
||||
|
||||
MAINTAINERS
|
||||
-----------
|
||||
|
||||
Current maintainers:
|
||||
* Facebook Inc. - https://www.drupal.org/u/facebook
|
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains facebook_pixel_settings_form.
|
||||
*/
|
||||
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelConfig;
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelOptions;
|
||||
|
||||
/**
|
||||
* Implements hook_admin_settings().
|
||||
*/
|
||||
function official_facebook_pixel_settings_form($form, &$form_state) {
|
||||
$options = OfficialFacebookPixelOptions::getInstance();
|
||||
|
||||
$form = array();
|
||||
|
||||
$form[OfficialFacebookPixelConfig::FORM_PIXEL_KEY] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t(OfficialFacebookPixelConfig::FORM_PIXEL_TITLE),
|
||||
'#description' => t(OfficialFacebookPixelConfig::FORM_PIXEL_DESCRIPTION),
|
||||
'#required' => TRUE,
|
||||
'#default_value' => $options->getPixelId(),
|
||||
);
|
||||
|
||||
$form[OfficialFacebookPixelConfig::FORM_PII_KEY] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t(OfficialFacebookPixelConfig::FORM_PII_TITLE),
|
||||
'#description' => t(sprintf(
|
||||
OfficialFacebookPixelConfig::FORM_PII_DESCRIPTION,
|
||||
OfficialFacebookPixelConfig::FORM_PII_DESCRIPTION_LINK)),
|
||||
'#default_value' => $options->getUsePii(),
|
||||
);
|
||||
|
||||
return system_settings_form($form);
|
||||
}
|
@ -0,0 +1,15 @@
|
||||
name = Official Facebook Pixel
|
||||
description = Official plugin provided by Facebook that will install a Facebook Pixel on your Drupal site.
|
||||
package = Statistics
|
||||
core = 7.x
|
||||
|
||||
dependencies[] = xautoload
|
||||
|
||||
configure = admin/config/system/official_facebook_pixel
|
||||
|
||||
; Information added by Drupal.org packaging script on 2018-12-07
|
||||
version = "7.x-1.1"
|
||||
core = "7.x"
|
||||
project = "officialfacebookpixel"
|
||||
datestamp = "1544223783"
|
||||
|
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains facebook_pixel.module.
|
||||
*/
|
||||
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelInjection;
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelOptions;
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelUtils;
|
||||
use Drupal\official_facebook_pixel\PixelScriptBuilder;
|
||||
|
||||
/**
|
||||
* Implements hook_permission().
|
||||
*/
|
||||
function official_facebook_pixel_permission() {
|
||||
return array(
|
||||
'admin' => array(
|
||||
'title' => t('Official Facebook Pixel Plugin Admin'),
|
||||
'description' => t('Official Facebook Pixel plugin admin.'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_menu().
|
||||
*/
|
||||
function official_facebook_pixel_menu() {
|
||||
$items = array();
|
||||
|
||||
$items['admin/config/system/official_facebook_pixel'] = array(
|
||||
'title' => t('Official Facebook Pixel Settings'),
|
||||
'description' => t('Configure Official Facebook Pixel.'),
|
||||
'page callback' => 'drupal_get_form',
|
||||
'page arguments' => array('official_facebook_pixel_settings_form'),
|
||||
'access arguments' => array('admin'),
|
||||
'type' => MENU_NORMAL_ITEM,
|
||||
'file' => 'official_facebook_pixel.admin.inc',
|
||||
);
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_page_build().
|
||||
*/
|
||||
function official_facebook_pixel_page_build(&$page) {
|
||||
if (!should_render()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$options = OfficialFacebookPixelOptions::getInstance();
|
||||
// Return if pixel_id is not positive integer
|
||||
if (!OfficialFacebookPixelUtils::isPositiveInteger($options->getPixelId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
OfficialFacebookPixelInjection::injectPixelCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if pixel code should be rendered
|
||||
*
|
||||
* @return boolean True is should render pixel code, otherwise false.
|
||||
*/
|
||||
function should_render() {
|
||||
global $user;
|
||||
$roles = $user->roles;
|
||||
return !(is_array($roles) && in_array("administrator", $roles));
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\official_facebook_pixel
|
||||
* \OfficialFacebookPixelConfig.
|
||||
*/
|
||||
|
||||
namespace Drupal\official_facebook_pixel;
|
||||
|
||||
/**
|
||||
* Class OfficialFacebookPixelConfig.
|
||||
*
|
||||
* @package Drupal\official_facebook_pixel
|
||||
*/
|
||||
class OfficialFacebookPixelConfig {
|
||||
const CONFIG_NAME = 'official_facebook_pixel.settings';
|
||||
const FORM_ID = 'official_facebook_pixel_settings';
|
||||
const FORM_PII_KEY = 'pii_id';
|
||||
const FORM_PII_TITLE = 'Use Advanced Matching on pixel?';
|
||||
const FORM_PII_DESCRIPTION = 'Enabling Advanced Matching improves audience building.<br />For businesses that operate in the European Union, you may need to take additional action. Read the <a href="%s" target="_blank">Cookie Consent Guide for Sites and Apps</a> for suggestions on complying with EU privacy requirements. the Facebook Pixel ID';
|
||||
const FORM_PII_DESCRIPTION_LINK = 'https://developers.facebook.com/docs/privacy/';
|
||||
const FORM_PIXEL_KEY = 'pixel_id';
|
||||
const FORM_PIXEL_TITLE = 'Pixel ID';
|
||||
const FORM_PIXEL_DESCRIPTION = 'Enter the Facebook Pixel ID';
|
||||
const SOURCE_7 = 'pldrupal-7';
|
||||
const SOURCE_8 = 'pldrupal-8';
|
||||
|
||||
// integration config for Drupal7: INTEGRATION_KEY => PLUGIN_CLASS
|
||||
public static function integrationConfigFor7() {
|
||||
return array(
|
||||
);
|
||||
}
|
||||
|
||||
// integration config for Drupal8: INTEGRATION_KEY => PLUGIN_CLASS
|
||||
public static function integrationConfigFor8() {
|
||||
return array(
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\official_facebook_pixel
|
||||
* \OfficialFacebookPixelInjection.
|
||||
*/
|
||||
|
||||
namespace Drupal\official_facebook_pixel;
|
||||
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelConfig;
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelOptions;
|
||||
|
||||
/**
|
||||
* Class OfficialFacebookPixelInjection.
|
||||
*
|
||||
* @package Drupal\official_facebook_pixel
|
||||
*/
|
||||
class OfficialFacebookPixelInjection {
|
||||
public static function injectPixelCode() {
|
||||
$options = OfficialFacebookPixelOptions::getInstance();
|
||||
PixelScriptBuilder::initialize($options->getPixelId());
|
||||
|
||||
self::injectScriptCode($options);
|
||||
self::injectNoScriptCode();
|
||||
|
||||
foreach (OfficialFacebookPixelConfig::integrationConfigFor7() as $key => $value) {
|
||||
$class_name = 'Drupal\\official_facebook_pixel\\integration\\'.$value;
|
||||
$class_name::injectPixelCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static function injectScriptCode($options) {
|
||||
// Inject inline script code to head
|
||||
$pixel_script_code = PixelScriptBuilder::getPixelBaseCode();
|
||||
$pixel_script_code .= PixelScriptBuilder::getPixelInitCode(
|
||||
$options->getAgentString(),
|
||||
$options->getUserInfo());
|
||||
$pixel_script_code .= PixelScriptBuilder::getPixelPageViewCode();
|
||||
drupal_add_html_head(
|
||||
[
|
||||
'#type' => 'markup',
|
||||
'#markup' => $pixel_script_code,
|
||||
'#weight' => 1000,
|
||||
],
|
||||
'facebook_pixel_script_code');
|
||||
}
|
||||
|
||||
public static function injectNoScriptCode() {
|
||||
// Inject inline noscript code to head
|
||||
$pixel_noscript_code = PixelScriptBuilder::getPixelNoscriptCode();
|
||||
drupal_add_html_head(
|
||||
[
|
||||
'#type' => 'markup',
|
||||
'#markup' => $pixel_noscript_code,
|
||||
'#weight' => 1000,
|
||||
],
|
||||
'facebook_pixel_noscript_code');
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\official_facebook_pixel
|
||||
* \OfficialFacebookPixelOptions.
|
||||
*/
|
||||
|
||||
namespace Drupal\official_facebook_pixel;
|
||||
|
||||
use Drupal\official_facebook_pixel\OfficialFacebookPixelConfig;
|
||||
|
||||
/**
|
||||
* Class OfficialFacebookPixelOptions.
|
||||
*
|
||||
* @package Drupal\official_facebook_pixel
|
||||
*/
|
||||
class OfficialFacebookPixelOptions {
|
||||
private static $instance = null;
|
||||
private $options = array();
|
||||
private $userInfo = array();
|
||||
private $versionInfo = array();
|
||||
|
||||
public static function getInstance() {
|
||||
if (is_null(self::$instance)) {
|
||||
self::$instance = new OfficialFacebookPixelOptions();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
$this->setOptions();
|
||||
$this->setUserInfo();
|
||||
$this->setVersionInfo();
|
||||
}
|
||||
|
||||
public function getOptions() {
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
private function setOptions() {
|
||||
$this->options = array(
|
||||
OfficialFacebookPixelConfig::FORM_PIXEL_KEY =>
|
||||
variable_get(OfficialFacebookPixelConfig::FORM_PIXEL_KEY, '3580569621997173'),
|
||||
OfficialFacebookPixelConfig::FORM_PII_KEY =>
|
||||
variable_get(OfficialFacebookPixelConfig::FORM_PII_KEY, 1),
|
||||
);
|
||||
}
|
||||
|
||||
public function getPixelId() {
|
||||
return $this->options[OfficialFacebookPixelConfig::FORM_PIXEL_KEY];
|
||||
}
|
||||
|
||||
public function getUsePii() {
|
||||
return $this->options[OfficialFacebookPixelConfig::FORM_PII_KEY];
|
||||
}
|
||||
|
||||
public function getUserInfo() {
|
||||
return $this->userInfo;
|
||||
}
|
||||
|
||||
public function setUserInfo() {
|
||||
global $user;
|
||||
$use_pii = $this->getUsePii();
|
||||
if (0 === $user->uid || $use_pii !== 1) {
|
||||
// User not logged in or admin chose not to send PII.
|
||||
$this->userInfo = array();
|
||||
} else {
|
||||
$this->userInfo = array_filter(
|
||||
array(
|
||||
// Keys documented in
|
||||
// https://developers.facebook.com/docs/facebook-pixel/pixel-with-ads/conversion-tracking#advanced_match
|
||||
'em' => $user->mail,
|
||||
),
|
||||
function ($value) { return $value !== null && $value !== ''; });
|
||||
}
|
||||
}
|
||||
|
||||
public function getVersionInfo() {
|
||||
return $this->versionInfo;
|
||||
}
|
||||
|
||||
public function setVersionInfo() {
|
||||
$this->versionInfo = array(
|
||||
'source' => OfficialFacebookPixelConfig::SOURCE_7,
|
||||
'version' => VERSION,
|
||||
);
|
||||
}
|
||||
|
||||
public function getAgentString() {
|
||||
return sprintf(
|
||||
'%s-%s',
|
||||
$this->versionInfo['source'],
|
||||
$this->versionInfo['version']);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\official_facebook_pixel
|
||||
* \OfficialFacebookPixelUtils.
|
||||
*/
|
||||
|
||||
namespace Drupal\official_facebook_pixel;
|
||||
|
||||
/**
|
||||
* Class OfficialFacebookPixelUtils.
|
||||
*
|
||||
* @package Drupal\official_facebook_pixel
|
||||
*/
|
||||
class OfficialFacebookPixelUtils {
|
||||
/**
|
||||
* Returns true if id is a positive non-zero integer
|
||||
*
|
||||
* @access public
|
||||
* @param string $pixel_id
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPositiveInteger($pixel_id) {
|
||||
return isset($pixel_id) && ctype_digit($pixel_id) && $pixel_id !== '0';
|
||||
}
|
||||
}
|
@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\official_facebook_pixel\PixelScriptBuilder.
|
||||
*/
|
||||
|
||||
namespace Drupal\official_facebook_pixel;
|
||||
|
||||
/**
|
||||
* Pixel object
|
||||
*/
|
||||
class PixelScriptBuilder {
|
||||
const ADDPAYMENTINFO = 'AddPaymentInfo';
|
||||
const ADDTOCART = 'AddToCart';
|
||||
const ADDTOWISHLIST = 'AddToWishlist';
|
||||
const COMPLETEREGISTRATION = 'CompleteRegistration';
|
||||
const CONTACT = 'Contact';
|
||||
const CUSTOMIZEPRODUCT = 'CustomizeProduct';
|
||||
const DONATE = 'Donate';
|
||||
const FINDLOCATION = 'FindLocation';
|
||||
const INITIATECHECKOUT = 'InitiateCheckout';
|
||||
const LEAD = 'Lead';
|
||||
const PAGEVIEW = 'PageView';
|
||||
const PURCHASE = 'Purchase';
|
||||
const SCHEDULE = 'Schedule';
|
||||
const SEARCH = 'Search';
|
||||
const STARTTRIAL = 'StartTrial';
|
||||
const SUBMITAPPLICATION = 'SubmitApplication';
|
||||
const SUBSCRIBE = 'Subscribe';
|
||||
const VIEWCONTENT = 'ViewContent';
|
||||
|
||||
const FB_INTEGRATION_TRACKING_KEY = 'fb_integration_tracking';
|
||||
|
||||
private static $pixelId = '';
|
||||
|
||||
private static $pixelBaseCode = "
|
||||
<!-- Facebook Pixel Code -->
|
||||
<script type='text/javascript'>
|
||||
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
||||
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
|
||||
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
|
||||
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
|
||||
document,'script','https://connect.facebook.net/en_US/fbevents.js');
|
||||
</script>
|
||||
<!-- End Facebook Pixel Code -->
|
||||
";
|
||||
|
||||
private static $pixelFbqCodeWithoutScript = "
|
||||
fbq('%s', '%s'%s%s);
|
||||
";
|
||||
|
||||
private static $pixelNoscriptCode = "
|
||||
<!-- Facebook Pixel Code -->
|
||||
<noscript>
|
||||
<img height=\"1\" width=\"1\" style=\"display:none\" alt=\"fbpx\"
|
||||
src=\"https://www.facebook.com/tr?id=%s&ev=%s%s&noscript=1\" />
|
||||
</noscript>
|
||||
<!-- End Facebook Pixel Code -->
|
||||
";
|
||||
|
||||
public static function initialize($pixel_id = '') {
|
||||
self::$pixelId = $pixel_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel ID
|
||||
*/
|
||||
public static function getPixelId() {
|
||||
return self::$pixelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets FB pixel ID
|
||||
*/
|
||||
public static function setPixelId($pixel_id) {
|
||||
self::$pixelId = $pixel_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel base code
|
||||
*/
|
||||
public static function getPixelBaseCode() {
|
||||
return self::$pixelBaseCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel init code
|
||||
*/
|
||||
public static function getPixelInitCode($agent_string, $param = array(), $with_script_tag = true) {
|
||||
if (empty(self::$pixelId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$code = $with_script_tag
|
||||
? "<script type='text/javascript'>" . self::$pixelFbqCodeWithoutScript . "</script>"
|
||||
: self::$pixelFbqCodeWithoutScript;
|
||||
$param_str = $param;
|
||||
if (is_array($param)) {
|
||||
$param_str = json_encode($param, JSON_PRETTY_PRINT);
|
||||
}
|
||||
$agent_param = array('agent' => $agent_string);
|
||||
return sprintf(
|
||||
$code,
|
||||
'init',
|
||||
self::$pixelId,
|
||||
', ' . $param_str,
|
||||
', ' . json_encode($agent_param, JSON_PRETTY_PRINT));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel track code
|
||||
* $param is the parameter for the pixel event.
|
||||
* If it is an array, FB_INTEGRATION_TRACKING_KEY parameter with $tracking_name value will automatically
|
||||
* be added into the $param. If it is a string, please append the FB_INTEGRATION_TRACKING_KEY parameter
|
||||
* with its tracking name into the JS Parameter block
|
||||
*/
|
||||
public static function getPixelTrackCode($event, $param = array(), $tracking_name = '', $with_script_tag = true) {
|
||||
if (empty(self::$pixelId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$code = $with_script_tag
|
||||
? "<script type='text/javascript'>" . self::$pixelFbqCodeWithoutScript . "</script>"
|
||||
: self::$pixelFbqCodeWithoutScript;
|
||||
$param_str = $param;
|
||||
if (is_array($param)) {
|
||||
if (!empty($tracking_name)) {
|
||||
$param[self::FB_INTEGRATION_TRACKING_KEY] = $tracking_name;
|
||||
}
|
||||
$param_str = json_encode($param, JSON_PRETTY_PRINT);
|
||||
}
|
||||
$class = new \ReflectionClass(__CLASS__);
|
||||
return sprintf(
|
||||
$code,
|
||||
$class->getConstant(strtoupper($event)) !== false ? 'track' : 'trackCustom',
|
||||
$event,
|
||||
', ' . $param_str,
|
||||
'');
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel noscript code
|
||||
*/
|
||||
public static function getPixelNoscriptCode($event = 'PageView', $cd = array(), $tracking_name = '') {
|
||||
if (empty(self::$pixelId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = '';
|
||||
foreach ($cd as $k => $v) {
|
||||
$data .= '&cd[' . $k . ']=' . $v;
|
||||
}
|
||||
if (!empty($tracking_name)) {
|
||||
$data .= '&cd[' . self::FB_INTEGRATION_TRACKING_KEY . ']=' . $tracking_name;
|
||||
}
|
||||
return sprintf(
|
||||
self::$pixelNoscriptCode,
|
||||
self::$pixelId,
|
||||
$event,
|
||||
$data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel AddToCart code
|
||||
*/
|
||||
public static function getPixelAddToCartCode($param = array(), $tracking_name = '', $with_script_tag = true) {
|
||||
return self::getPixelTrackCode(
|
||||
self::ADDTOCART,
|
||||
$param,
|
||||
$tracking_name,
|
||||
$with_script_tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel InitiateCheckout code
|
||||
*/
|
||||
public static function getPixelInitiateCheckoutCode($param = array(), $tracking_name = '', $with_script_tag = true) {
|
||||
return self::getPixelTrackCode(
|
||||
self::INITIATECHECKOUT,
|
||||
$param,
|
||||
$tracking_name,
|
||||
$with_script_tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel Lead code
|
||||
*/
|
||||
public static function getPixelLeadCode($param = array(), $tracking_name = '', $with_script_tag = true) {
|
||||
return self::getPixelTrackCode(
|
||||
self::LEAD,
|
||||
$param,
|
||||
$tracking_name,
|
||||
$with_script_tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel PageView code
|
||||
*/
|
||||
public static function getPixelPageViewCode($param = array(), $tracking_name = '', $with_script_tag = true) {
|
||||
return self::getPixelTrackCode(
|
||||
self::PAGEVIEW,
|
||||
$param,
|
||||
$tracking_name,
|
||||
$with_script_tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel Purchase code
|
||||
*/
|
||||
public static function getPixelPurchaseCode($param = array(), $tracking_name = '', $with_script_tag = true) {
|
||||
return self::getPixelTrackCode(
|
||||
self::PURCHASE,
|
||||
$param,
|
||||
$tracking_name,
|
||||
$with_script_tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets FB pixel ViewContent code
|
||||
*/
|
||||
public static function getPixelViewContentCode($param = array(), $tracking_name = '', $with_script_tag = true) {
|
||||
return self::getPixelTrackCode(
|
||||
self::VIEWCONTENT,
|
||||
$param,
|
||||
$tracking_name,
|
||||
$with_script_tag);
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\official_facebook_pixel
|
||||
* \integration\FacebookDrupalExample.
|
||||
*/
|
||||
|
||||
namespace Drupal\official_facebook_pixel\integration;
|
||||
|
||||
/**
|
||||
* Class FacebookDrupalExample.
|
||||
*
|
||||
* @package Drupal\official_facebook_pixel\integration
|
||||
*/
|
||||
|
||||
class FacebookDrupalExample extends FacebookDrupalIntegrationBase {
|
||||
const TRACKING_NAME = 'example';
|
||||
|
||||
public static function injectPixelCode() {
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\official_facebook_pixel
|
||||
* \integration\FacebookDrupalIntegrationBase.
|
||||
*/
|
||||
|
||||
namespace Drupal\official_facebook_pixel\integration;
|
||||
|
||||
/**
|
||||
* Class FacebookDrupalIntegrationBase.
|
||||
*
|
||||
* @package Drupal\official_facebook_pixel\integration
|
||||
*/
|
||||
|
||||
abstract class FacebookDrupalIntegrationBase {
|
||||
const TRACKING_NAME = '';
|
||||
|
||||
/**
|
||||
* inject the pixel code for the plugin
|
||||
*/
|
||||
public static function injectPixelCode() {
|
||||
}
|
||||
}
|
5
frontend/drupal/modules/xautoload/.travis.yml
Normal file
5
frontend/drupal/modules/xautoload/.travis.yml
Normal file
@ -0,0 +1,5 @@
|
||||
language: php
|
||||
php:
|
||||
- 5.5
|
||||
- 5.4
|
||||
- 5.3
|
339
frontend/drupal/modules/xautoload/LICENSE.txt
Normal file
339
frontend/drupal/modules/xautoload/LICENSE.txt
Normal file
@ -0,0 +1,339 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
3
frontend/drupal/modules/xautoload/README.md
Normal file
3
frontend/drupal/modules/xautoload/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
[](https://travis-ci.org/donquixote/drupal-xautoload)
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* This class is not used anywhere in xautoload, but could be used by other
|
||||
* modules.
|
||||
*/
|
||||
class xautoload_FinderPlugin_CheckIncludePath implements xautoload_FinderPlugin_Interface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function findFile($api, $logical_base_path, $relative_path) {
|
||||
$path = $logical_base_path . $relative_path;
|
||||
return $api->suggestFile_checkIncludePath($path);
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\InjectedApiInterface;
|
||||
use Drupal\xautoload\DirectoryBehavior\DirectoryBehaviorInterface;
|
||||
|
||||
/**
|
||||
* X Autoload plugins are for:
|
||||
* - More exotic autoload patterns that are incompatible with PSR-0 or PEAR
|
||||
* - Situations where we don't want to register a ton of namespaces, and using
|
||||
* a plugin instead gives us performance benefits.
|
||||
*/
|
||||
interface xautoload_FinderPlugin_Interface extends DirectoryBehaviorInterface {
|
||||
|
||||
/**
|
||||
* Find the file for a class that in PSR-0 or PEAR would be in
|
||||
* $psr_0_root . '/' . $path_fragment . $path_suffix
|
||||
*
|
||||
* E.g.:
|
||||
* - The class we look for is Some\Namespace\Some\Class
|
||||
* - The file is actually in "exotic/location.php". This is not following
|
||||
* PSR-0 or PEAR standard, so we need a plugin.
|
||||
* -> The class finder will transform the class name to
|
||||
* "Some/Namespace/Some/Class.php"
|
||||
* - The plugin was registered for the namespace "Some\Namespace". This is
|
||||
* because all those exotic classes all begin with Some\Namespace\
|
||||
* -> The arguments will be:
|
||||
* ($api = the API object, see below)
|
||||
* $logical_base_path = "Some/Namespace/"
|
||||
* $relative_path = "Some/Class.php"
|
||||
* $api->getClass() gives the original class name, if we still need it.
|
||||
* -> We are supposed to:
|
||||
* if ($api->suggestFile('exotic/location.php')) {
|
||||
* return TRUE;
|
||||
* }
|
||||
*
|
||||
* @param InjectedApiInterface $api
|
||||
* An object with a suggestFile() method.
|
||||
* We are supposed to suggest files until suggestFile() returns TRUE, or we
|
||||
* have no more suggestions.
|
||||
* @param string $logical_base_path
|
||||
* The key that this plugin was registered with.
|
||||
* With trailing '/'.
|
||||
* @param string $relative_path
|
||||
* Second part of the canonical path, ending with '.php'.
|
||||
*
|
||||
* @return bool|null
|
||||
* TRUE, if the file was found.
|
||||
* FALSE or NULL, otherwise.
|
||||
*/
|
||||
function findFile($api, $logical_base_path, $relative_path);
|
||||
}
|
@ -0,0 +1,248 @@
|
||||
<?php
|
||||
|
||||
use Drupal\xautoload\Adapter\LocalDirectoryAdapter;
|
||||
use Drupal\xautoload\Util;
|
||||
use Drupal\xautoload\ClassFinder\ExtendedClassFinderInterface;
|
||||
use Drupal\xautoload\Adapter\ClassFinderAdapter;
|
||||
|
||||
/**
|
||||
* An instance of this class is passed around to implementations of
|
||||
* hook_xautoload(). It acts as a wrapper around the ClassFinder, to register
|
||||
* stuff.
|
||||
*
|
||||
* Most of the methods here are deprecated. You should use the methods inherited
|
||||
* from the base class, LocalDirectoryAdapter, instead.
|
||||
*/
|
||||
class xautoload_InjectedAPI_hookXautoload extends LocalDirectoryAdapter {
|
||||
|
||||
/**
|
||||
* @var ExtendedClassFinderInterface
|
||||
*/
|
||||
protected $finder;
|
||||
|
||||
/**
|
||||
* @param ExtendedClassFinderInterface $finder
|
||||
* The class finder object.
|
||||
* @param string $localDirectory
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
static function create($finder, $localDirectory) {
|
||||
$adapter = ClassFinderAdapter::create($finder);
|
||||
return new self($adapter, $localDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassFinderAdapter $adapter
|
||||
* The class finder object.
|
||||
* @param string $localDirectory
|
||||
*/
|
||||
function __construct($adapter, $localDirectory) {
|
||||
parent::__construct($adapter, $localDirectory);
|
||||
$this->finder = $adapter->getFinder();
|
||||
}
|
||||
|
||||
// Prefix stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register an additional prefix for this module.
|
||||
* Note: Drupal\<module name>\ is already registered for <module dir>/lib.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $prefix
|
||||
* The prefix.
|
||||
* @param string $prefix_root_dir
|
||||
* Prefix root dir.
|
||||
* If $relative is TRUE, this is relative to the extension module dir.
|
||||
* If $relative is FALSE, this is an absolute path.
|
||||
* @param boolean $relative
|
||||
* Whether or not the path is relative to the current extension dir.
|
||||
*/
|
||||
function prefixRoot($prefix, $prefix_root_dir = NULL, $relative = TRUE) {
|
||||
$prefix_root_dir = $this->processDir($prefix_root_dir, $relative);
|
||||
$this->finder->registerPrefixRoot($prefix, $prefix_root_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an additional namespace for this module.
|
||||
* Note: Drupal\<module name>\ is already registered for <module dir>/lib.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $prefix
|
||||
* The namespace
|
||||
* @param string $prefix_deep_dir
|
||||
* PSR-0 root dir.
|
||||
* If $relative is TRUE, this is relative to the current extension dir.
|
||||
* If $relative is FALSE, this is an absolute path.
|
||||
* @param boolean $relative
|
||||
* Whether or not the path is relative to the current extension dir.
|
||||
*/
|
||||
function prefixDeep($prefix, $prefix_deep_dir = NULL, $relative = TRUE) {
|
||||
$prefix_deep_dir = $this->processDir($prefix_deep_dir, $relative);
|
||||
$this->finder->registerPrefixDeep($prefix, $prefix_deep_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy: Plugins were called "Handler" before.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param xautoload_FinderPlugin_Interface $plugin
|
||||
*
|
||||
* @return string
|
||||
* The key under which the plugin was registered. This can later be used to
|
||||
* unregister the plugin again.
|
||||
*/
|
||||
function prefixHandler($prefix, $plugin) {
|
||||
$key = Util::randomString();
|
||||
$this->finder->registerPrefixDeep($prefix, $key, $plugin);
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a prefix plugin object
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param xautoload_FinderPlugin_Interface $plugin
|
||||
*
|
||||
* @return string
|
||||
* The key under which the plugin was registered. This can later be used to
|
||||
* unregister the plugin again.
|
||||
*/
|
||||
function prefixPlugin($prefix, $plugin) {
|
||||
$key = Util::randomString();
|
||||
$this->finder->registerPrefixDeep($prefix, $key, $plugin);
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
// Namespace stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register an additional namespace for this module.
|
||||
* Note: Drupal\<module name>\ is already registered for <module dir>/lib.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $namespace
|
||||
* The namespace
|
||||
* @param string $psr_0_root_dir
|
||||
* PSR-0 root dir.
|
||||
* If $relative is TRUE, this is relative to the current module dir.
|
||||
* If $relative is FALSE, this is an absolute path.
|
||||
* @param boolean $relative
|
||||
* Whether or not the path is relative to the current extension dir.
|
||||
*/
|
||||
function namespaceRoot($namespace, $psr_0_root_dir = NULL, $relative = TRUE) {
|
||||
$psr_0_root_dir = $this->processDir($psr_0_root_dir, $relative);
|
||||
$this->finder->registerNamespaceRoot($namespace, $psr_0_root_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an additional namespace for this module.
|
||||
* Note: Drupal\<module name>\ is already registered for <module dir>/lib.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $namespace
|
||||
* The namespace
|
||||
* @param string $namespace_deep_dir
|
||||
* PSR-0 root dir.
|
||||
* If $relative is TRUE, this is relative to the current extension dir.
|
||||
* If $relative is FALSE, this is an absolute path.
|
||||
* @param boolean $relative
|
||||
* Whether or not the path is relative to the current extension dir.
|
||||
*/
|
||||
function namespaceDeep($namespace, $namespace_deep_dir = NULL, $relative = TRUE) {
|
||||
$namespace_deep_dir = $this->processDir($namespace_deep_dir, $relative);
|
||||
$this->finder->registerNamespaceDeep($namespace, $namespace_deep_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a namespace plugin object
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param xautoload_FinderPlugin_Interface $plugin
|
||||
*
|
||||
* @return string
|
||||
* The key under which the plugin was registered. This can later be used to
|
||||
* unregister the plugin again.
|
||||
*/
|
||||
function namespacePlugin($namespace, $plugin) {
|
||||
$key = Util::randomString();
|
||||
$this->finder->registerNamespaceDeep($namespace, $key, $plugin);
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Legacy: Plugins were called "Handler" before.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $namespace
|
||||
* @param xautoload_FinderPlugin_Interface $plugin
|
||||
*
|
||||
* @return string
|
||||
* The key under which the plugin was registered. This can later be used to
|
||||
* unregister the plugin again.
|
||||
*/
|
||||
function namespaceHandler($namespace, $plugin) {
|
||||
$key = Util::randomString();
|
||||
$this->finder->registerNamespaceDeep($namespace, $key, $plugin);
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a given directory to make it relative to Drupal root,
|
||||
* instead of relative to the current extension dir.
|
||||
*
|
||||
* @deprecated
|
||||
*
|
||||
* @param string $dir
|
||||
* The directory path that we want to make absolute.
|
||||
* @param boolean $relative
|
||||
* If TRUE, the $dir will be transformed from relative to absolute.
|
||||
* If FALSE, the $dir is assumed to already be absolute, and remain unchanged.
|
||||
*
|
||||
* @return string
|
||||
* The modified (absolute) directory path.
|
||||
*/
|
||||
protected function processDir($dir, $relative) {
|
||||
if (!isset($dir)) {
|
||||
return $this->localDirectory . 'lib/';
|
||||
}
|
||||
$dir = strlen($dir)
|
||||
? rtrim($dir, '/') . '/'
|
||||
: '';
|
||||
|
||||
return $relative
|
||||
? $this->localDirectory . $dir
|
||||
: $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explicitly set the base for relative paths.
|
||||
*
|
||||
* Alias for LocalDirectoryAdapter::setLocalDirectory()
|
||||
*
|
||||
* @param string $dir
|
||||
* New relative base path.
|
||||
*/
|
||||
function setExtensionDir($dir) {
|
||||
$this->localDirectory = strlen($dir)
|
||||
? rtrim($dir, '/') . '/'
|
||||
: '';
|
||||
}
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Tests;
|
||||
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
class EnvironmentSnapshotMaker {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected static $snapshots = array();
|
||||
|
||||
/**
|
||||
* @param string $module
|
||||
* @param string $phase
|
||||
* @param string[] $classes
|
||||
*/
|
||||
static function takeSnapshot($module, $phase, $classes) {
|
||||
self::$snapshots[$module][$phase] = self::buildSnapshot($classes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $module
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
static function getSnapshots($module) {
|
||||
return isset(self::$snapshots[$module])
|
||||
? self::$snapshots[$module]
|
||||
: array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classes
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function buildSnapshot($classes) {
|
||||
|
||||
$observations = array();
|
||||
|
||||
// Test that all classes are available immediately at boot time.
|
||||
foreach ($classes as $class) {
|
||||
$observations['class_exists'][$class] = class_exists($class);
|
||||
}
|
||||
|
||||
// Check variable_get().
|
||||
$observations[XAUTOLOAD_VARNAME_CACHE_TYPES] = variable_get(XAUTOLOAD_VARNAME_CACHE_TYPES);
|
||||
$observations[XAUTOLOAD_VARNAME_CACHE_LAZY] = variable_get(XAUTOLOAD_VARNAME_CACHE_LAZY);
|
||||
|
||||
$observations['db_connection_info'] = \Database::getConnectionInfo();
|
||||
|
||||
$spl_autoload_stack = array();
|
||||
foreach (spl_autoload_functions() as $callback) {
|
||||
$spl_autoload_stack[] = Util::callbackToString($callback);
|
||||
}
|
||||
$observations['spl_autoload_functions'] = $spl_autoload_stack;
|
||||
|
||||
return $observations;
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Tests;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\ClassFinder;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\CollectFilesInjectedApi;
|
||||
use Drupal\xautoload\ClassLoader\ClassLoaderInterface;
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
class XAutoloadUnitTestCase extends \DrupalUnitTestCase {
|
||||
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'X Autoload unit test',
|
||||
'description' => 'Test the xautoload class finder.',
|
||||
'group' => 'X Autoload',
|
||||
);
|
||||
}
|
||||
|
||||
function setUp() {
|
||||
|
||||
// drupal_load('module', 'xautoload') would register namespaces for all
|
||||
// enabled modules, which is not intended for this unit test.
|
||||
// Instead, we just include xautoload.early.inc.
|
||||
require_once __DIR__ . '/../../../../xautoload.early.inc';
|
||||
|
||||
// Make sure we use the regular loader, not the APC one.
|
||||
// Also make sure to prepend this one. Otherwise, the core class loader will
|
||||
// try to load xautoload-related stuff, e.g. xautoload_Mock_* stuff, and
|
||||
// will fail due to the database.
|
||||
foreach (spl_autoload_functions() as $callback) {
|
||||
if (is_array($callback)
|
||||
&& ($loader = $callback[0])
|
||||
&& $loader instanceof ClassLoaderInterface
|
||||
) {
|
||||
$loader->unregister();
|
||||
}
|
||||
}
|
||||
xautoload()->finder->register(TRUE);
|
||||
|
||||
// Do the regular setUp().
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
function testAutoloadStackOrder() {
|
||||
$expected = array(
|
||||
'Drupal\\xautoload\\ClassFinder\\ClassFinder->loadClass()',
|
||||
/* @see _drupal_bootstrap_database() */
|
||||
'drupal_autoload_class',
|
||||
'drupal_autoload_interface',
|
||||
/* @see simpletest_classloader_register() */
|
||||
'_simpletest_autoload_psr4_psr0',
|
||||
);
|
||||
|
||||
$actual = array();
|
||||
foreach (spl_autoload_functions() as $callback) {
|
||||
$actual[] = Util::callbackToString($callback);
|
||||
}
|
||||
|
||||
$this->assertEqualBlock($expected, $actual, "SPL autoload stack:");
|
||||
}
|
||||
|
||||
function testNamespaces() {
|
||||
|
||||
// Prepare the class finder.
|
||||
$finder = new ClassFinder();
|
||||
$finder->add('Drupal\\ex_ample', 'sites/all/modules/contrib/ex_ample/lib-psr0');
|
||||
$finder->addPsr4('Drupal\\ex_ample', 'sites/all/modules/contrib/ex_ample/lib-psr4');
|
||||
|
||||
// Test class finding for 'Drupal\\ex_ample\\Abc_Def'.
|
||||
$this->assertFinderSuggestions($finder, 'Drupal\\ex_ample\\Abc_Def', array(
|
||||
// Class finder is expected to suggest these files, in the exact order,
|
||||
// until one of them is accepted.
|
||||
array('suggestFile', 'sites/all/modules/contrib/ex_ample/lib-psr0/Drupal/ex_ample/Abc/Def.php'),
|
||||
array('suggestFile', 'sites/all/modules/contrib/ex_ample/lib-psr4/Abc_Def.php'),
|
||||
));
|
||||
}
|
||||
|
||||
function testPrefixes() {
|
||||
|
||||
// Prepare the class finder.
|
||||
$finder = new ClassFinder();
|
||||
$finder->registerPrefixDeep('ex_ample', 'sites/all/modules/contrib/ex_ample/lib');
|
||||
$finder->registerPrefixRoot('ex_ample', 'sites/all/modules/contrib/ex_ample/vendor');
|
||||
|
||||
// Test class finding for 'ex_ample_Abc_Def'.
|
||||
$this->assertFinderSuggestions($finder, 'ex_ample_Abc_Def', array(
|
||||
// Class finder is expected to suggest these files, in the exact order,
|
||||
// until one of them is accepted.
|
||||
array('suggestFile', 'sites/all/modules/contrib/ex_ample/lib/Abc/Def.php'),
|
||||
array('suggestFile', 'sites/all/modules/contrib/ex_ample/vendor/ex/ample/Abc/Def.php'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassFinder $finder
|
||||
* @param string $class
|
||||
* @param array $expectedSuggestions
|
||||
*
|
||||
* @return bool
|
||||
* Result of the assertion
|
||||
*/
|
||||
protected function assertFinderSuggestions($finder, $class, array $expectedSuggestions) {
|
||||
$success = TRUE;
|
||||
for ($iAccept = 0; $iAccept < count($expectedSuggestions); ++$iAccept) {
|
||||
list($method_name, $file) = $expectedSuggestions[$iAccept];
|
||||
$api = new CollectFilesInjectedApi($class, $method_name, $file);
|
||||
$finder->apiFindFile($api, $class);
|
||||
$suggestions = $api->getSuggestions();
|
||||
$expected = array_slice($expectedSuggestions, 0, $iAccept + 1);
|
||||
$success = $success && $this->assertEqualBlock($expected, $suggestions, "Finder suggestions for class <code>$class</code>:");
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $expected
|
||||
* @param mixed $actual
|
||||
* @param string $label
|
||||
*
|
||||
* @return bool
|
||||
* Result of the assertion
|
||||
*/
|
||||
protected function assertEqualBlock($expected, $actual, $label) {
|
||||
$label .= '<br/>' .
|
||||
'Expected: <pre>' . var_export($expected, TRUE) . '</pre>' .
|
||||
'Actual: <pre>' . var_export($actual, TRUE) . '</pre>';
|
||||
return $this->assertEqual($expected, $actual, $label);
|
||||
}
|
||||
}
|
@ -0,0 +1,264 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Tests;
|
||||
|
||||
class XAutoloadWebTestCase extends \DrupalWebTestCase {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
static function getInfo() {
|
||||
return array(
|
||||
'name' => 'X Autoload web test',
|
||||
'description' => 'Test xautoload class loading for an example module.',
|
||||
'group' => 'X Autoload',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function testNoCache() {
|
||||
$this->xautoloadTestWithCacheTypes(array(), TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function testApcCache() {
|
||||
$cache_types = array(
|
||||
'apc' => 'apc',
|
||||
'xcache' => 'xcache',
|
||||
'wincache' => 'wincache',
|
||||
);
|
||||
$this->xautoloadTestWithCacheTypes($cache_types, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $cache_types
|
||||
* The autoloader modes that are enabled, e.g.
|
||||
* array('apc' => 'apc', 'xcache' => 'xcache')
|
||||
* @param bool $cache_lazy
|
||||
* Whether the "lazy" mode is enabled.
|
||||
*/
|
||||
protected function xautoloadTestWithCacheTypes($cache_types, $cache_lazy) {
|
||||
|
||||
variable_set(XAUTOLOAD_VARNAME_CACHE_TYPES, $cache_types);
|
||||
$this->pass("Set cache types: " . var_export($cache_types, TRUE));
|
||||
|
||||
variable_set(XAUTOLOAD_VARNAME_CACHE_LAZY, $cache_lazy);
|
||||
$this->pass("Set cache lazy mode: " . var_export($cache_lazy, TRUE));
|
||||
|
||||
// Enable xautoload.
|
||||
module_enable(array('xautoload'), FALSE);
|
||||
|
||||
// At this time the xautoload_cache_mode setting is not in effect yet,
|
||||
// so we have to clear old cached values from APC cache.
|
||||
xautoload()->cacheManager->renewCachePrefix();
|
||||
|
||||
module_enable(array(
|
||||
'xautoload_test_1',
|
||||
'xautoload_test_2',
|
||||
'xautoload_test_3',
|
||||
'xautoload_test_4',
|
||||
'xautoload_test_5',
|
||||
), FALSE);
|
||||
menu_rebuild();
|
||||
|
||||
foreach (array(
|
||||
'xautoload_test_1' => array('Drupal\xautoload_test_1\ExampleClass'),
|
||||
'xautoload_test_2' => array('xautoload_test_2_ExampleClass'),
|
||||
'xautoload_test_3' => array('Drupal\xautoload_test_3\ExampleClass'),
|
||||
) as $module => $classes) {
|
||||
$classes_on_include = in_array($module, array('xautoload_test_2', 'xautoload_test_3'));
|
||||
$this->xautoloadModuleEnabled($module, $classes, $classes_on_include);
|
||||
$this->xautoloadModuleCheckJson($module, $cache_types, $cache_lazy, $classes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $module
|
||||
* @param string[] $classes
|
||||
* @param bool $classes_on_include
|
||||
*/
|
||||
protected function xautoloadModuleEnabled($module, $classes, $classes_on_include) {
|
||||
|
||||
EnvironmentSnapshotMaker::takeSnapshot($module, 'later', $classes);
|
||||
|
||||
$all = EnvironmentSnapshotMaker::getSnapshots($module);
|
||||
|
||||
foreach ($all as $phase => $observations) {
|
||||
$when = ($phase === 'early')
|
||||
? 'on drupal_load() during module_enable()'
|
||||
: (($phase === 'later')
|
||||
? 'after hook_modules_enabled()'
|
||||
: 'at an undefined time'
|
||||
);
|
||||
|
||||
// Test the classes of the example module.
|
||||
foreach ($classes as $class) {
|
||||
// Test that the class was already found in $phase.
|
||||
$this->assertTrue(isset($observations['class_exists'][$class]), "Class $class was checked $when.");
|
||||
if ($classes_on_include || $phase !== 'early') {
|
||||
$this->assertTrue($observations['class_exists'][$class], "Class $class was found $when.");
|
||||
}
|
||||
else {
|
||||
$this->assertFalse($observations['class_exists'][$class], "Class $class cannot be found $when.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $module
|
||||
* @param array $cache_types
|
||||
* The autoloader modes that are enabled, e.g.
|
||||
* array('apc' => 'apc', 'xcache' => 'xcache')
|
||||
* @param bool $cache_lazy
|
||||
* Whether the "lazy" mode is enabled.
|
||||
* @param string[] $classes
|
||||
*/
|
||||
protected function xautoloadModuleCheckJson($module, $cache_types, $cache_lazy, $classes) {
|
||||
|
||||
$path = "$module.json";
|
||||
$json = $this->drupalGet($path);
|
||||
$all = json_decode($json, TRUE);
|
||||
|
||||
if (!is_array($all) || empty($all)) {
|
||||
$this->fail("$path must return a non-empty json array.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($all as $phase => $observations) {
|
||||
|
||||
$when = ($phase === 'early')
|
||||
? 'on early bootstrap'
|
||||
: (($phase === 'boot')
|
||||
? 'during hook_boot()'
|
||||
: 'at an undefined time'
|
||||
);
|
||||
|
||||
$this->xautoloadCheckTestEnvironment($observations, $cache_types, $cache_lazy, $when);
|
||||
|
||||
// Test the classes of the example module.
|
||||
foreach ($classes as $class) {
|
||||
// Test that the class was already found in $phase.
|
||||
$this->assertTrue($observations['class_exists'][$class], "Class $class was found $when.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $observations
|
||||
* @param array $cache_types
|
||||
* The autoloader modes that are enabled, e.g.
|
||||
* array('apc' => 'apc', 'xcache' => 'xcache')
|
||||
* @param bool $lazy
|
||||
* Whether the "lazy" mode is enabled.
|
||||
* @param $when
|
||||
*/
|
||||
protected function xautoloadCheckTestEnvironment($observations, $cache_types, $lazy, $when) {
|
||||
|
||||
// Check early-bootstrap variables.
|
||||
$label = "$when: xautoload_cache_types:";
|
||||
$this->assertEqualBlock($cache_types, $observations[XAUTOLOAD_VARNAME_CACHE_TYPES], $label);
|
||||
|
||||
$label = "$when: xautoload_cache_lazy:";
|
||||
$this->assertEqualInline($lazy, $observations[XAUTOLOAD_VARNAME_CACHE_LAZY], $label);
|
||||
|
||||
// Check registered class loaders.
|
||||
$expected = $this->expectedAutoloadStackOrder($cache_types);
|
||||
$actual = $observations['spl_autoload_functions'];
|
||||
$label = "$when: spl autoload stack:";
|
||||
$this->assertEqualBlock($expected, $actual, $label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $cache_types
|
||||
* The autoloader modes that are enabled, e.g.
|
||||
* array('apc' => 'apc', 'xcache' => 'xcache')
|
||||
*
|
||||
* @return string[]
|
||||
* Expected order of class loaders on the spl autoload stack for the given
|
||||
* autoloader mode. Each represented by a string.
|
||||
*/
|
||||
protected function expectedAutoloadStackOrder($cache_types) {
|
||||
|
||||
if (!empty($cache_types['apc']) && extension_loaded('apc') && function_exists('apc_store')) {
|
||||
$loader = 'Drupal\xautoload\ClassLoader\ApcClassLoader->loadClass()';
|
||||
}
|
||||
elseif (!empty($cache_types['wincache']) && extension_loaded('wincache') && function_exists('wincache_ucache_get')) {
|
||||
$loader = 'Drupal\xautoload\ClassLoader\WinCacheClassLoader->loadClass()';
|
||||
}
|
||||
elseif (!empty($cache_types['xcache']) && extension_loaded('Xcache') && function_exists('xcache_get')) {
|
||||
$loader = 'Drupal\xautoload\ClassLoader\XCacheClassLoader->loadClass()';
|
||||
}
|
||||
else {
|
||||
$loader = 'Drupal\xautoload\ClassFinder\ClassFinder->loadClass()';
|
||||
}
|
||||
|
||||
return array(
|
||||
'drupal_autoload_class',
|
||||
'drupal_autoload_interface',
|
||||
$loader,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a module is disabled.
|
||||
*
|
||||
* @param string $module
|
||||
*/
|
||||
protected function assertModuleDisabled($module) {
|
||||
$this->assertFalse(module_exists($module), "Module $module is disabled.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a module is enabled.
|
||||
*
|
||||
* @param string $module
|
||||
*/
|
||||
protected function assertModuleEnabled($module) {
|
||||
$this->assertTrue(module_exists($module), "Module $module is enabled.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that a class is defined.
|
||||
*
|
||||
* @param string $class
|
||||
*/
|
||||
protected function assertClassExists($class) {
|
||||
$this->assertTrue(class_exists($class), "Class '$class' must exist.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $expected
|
||||
* @param mixed $actual
|
||||
* @param string $label
|
||||
*/
|
||||
protected function assertEqualBlock($expected, $actual, $label) {
|
||||
$label .=
|
||||
'Expected: <pre>' . var_export($expected, TRUE) . '</pre>' .
|
||||
'Actual: <pre>' . var_export($actual, TRUE) . '</pre>';
|
||||
$this->assertEqual($expected, $actual, $label);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $expected
|
||||
* @param mixed $actual
|
||||
* @param string $label
|
||||
*/
|
||||
protected function assertEqualInline($expected, $actual, $label) {
|
||||
$label .= '<br/>' .
|
||||
'Expected: <code>' . var_export($expected, TRUE) . '</code><br/>' .
|
||||
'Actual: <code>' . var_export($actual, TRUE) . '</code>';
|
||||
$this->assertEqual($expected, $actual, $label);
|
||||
}
|
||||
}
|
19
frontend/drupal/modules/xautoload/phpunit.xml.dist
Normal file
19
frontend/drupal/modules/xautoload/phpunit.xml.dist
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<phpunit backupGlobals="false"
|
||||
backupStaticAttributes="false"
|
||||
colors="true"
|
||||
convertErrorsToExceptions="true"
|
||||
convertNoticesToExceptions="true"
|
||||
convertWarningsToExceptions="true"
|
||||
processIsolation="false"
|
||||
stopOnFailure="false"
|
||||
syntaxCheck="false"
|
||||
bootstrap="tests/bootstrap.php"
|
||||
>
|
||||
<testsuites>
|
||||
<testsuite name="XAutoload Test Suite">
|
||||
<directory>./tests/src</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
@ -0,0 +1,287 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\Adapter;
|
||||
|
||||
use Drupal\xautoload\Discovery\ClassMapGenerator;
|
||||
use Drupal\xautoload\Util;
|
||||
use Drupal\xautoload\DirectoryBehavior\DefaultDirectoryBehavior;
|
||||
use Drupal\xautoload\Discovery\ComposerDir;
|
||||
use Drupal\xautoload\Discovery\ComposerJson;
|
||||
use Drupal\xautoload\ClassFinder\GenericPrefixMap;
|
||||
use Drupal\xautoload\DirectoryBehavior\Psr0DirectoryBehavior;
|
||||
use Drupal\xautoload\ClassFinder\ExtendedClassFinderInterface;
|
||||
use Drupal\xautoload\Discovery\ClassMapGeneratorInterface;
|
||||
|
||||
/**
|
||||
* An instance of this class is passed around to implementations of
|
||||
* hook_xautoload(). It acts as a wrapper around the ClassFinder, to register
|
||||
* stuff.
|
||||
*/
|
||||
class ClassFinderAdapter implements ClassFinderAdapterInterface {
|
||||
|
||||
/**
|
||||
* @var ExtendedClassFinderInterface
|
||||
*/
|
||||
protected $finder;
|
||||
|
||||
/**
|
||||
* @var GenericPrefixMap
|
||||
*/
|
||||
protected $prefixMap;
|
||||
|
||||
/**
|
||||
* @var GenericPrefixMap
|
||||
*/
|
||||
protected $namespaceMap;
|
||||
|
||||
/**
|
||||
* @var ClassMapGeneratorInterface
|
||||
*/
|
||||
protected $classMapGenerator;
|
||||
|
||||
/**
|
||||
* @param ExtendedClassFinderInterface $finder
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
static function create($finder) {
|
||||
return new self($finder, new ClassMapGenerator());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ExtendedClassFinderInterface $finder
|
||||
* The class finder object.
|
||||
* @param ClassMapGeneratorInterface $classmap_generator
|
||||
*/
|
||||
function __construct($finder, $classmap_generator) {
|
||||
$this->finder = $finder;
|
||||
$this->prefixMap = $finder->getPrefixMap();
|
||||
$this->namespaceMap = $finder->getNamespaceMap();
|
||||
$this->defaultBehavior = new DefaultDirectoryBehavior();
|
||||
$this->psr0Behavior = new Psr0DirectoryBehavior();
|
||||
$this->classMapGenerator = $classmap_generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Drupal\xautoload\ClassFinder\GenericPrefixMap
|
||||
*/
|
||||
function getNamespaceMap() {
|
||||
return $this->namespaceMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GenericPrefixMap
|
||||
*/
|
||||
function getPrefixMap() {
|
||||
return $this->prefixMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassMapGeneratorInterface
|
||||
*/
|
||||
function getClassmapGenerator() {
|
||||
return $this->classMapGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassMapGeneratorInterface
|
||||
*/
|
||||
function getFinder() {
|
||||
return $this->finder;
|
||||
}
|
||||
|
||||
// Discovery
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addClassmapSources($paths) {
|
||||
$map = $this->classMapGenerator->wildcardPathsToClassmap($paths);
|
||||
$this->addClassMap($map);
|
||||
}
|
||||
|
||||
// Composer tools
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function composerJson($file) {
|
||||
$json = ComposerJson::createFromFile($file);
|
||||
$json->writeToAdapter($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function composerDir($dir) {
|
||||
$dir = ComposerDir::create($dir);
|
||||
$dir->writeToAdapter($this);
|
||||
}
|
||||
|
||||
// multiple PSR-0 / PSR-4
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addMultiplePsr0(array $prefixes) {
|
||||
$namespace_map = array();
|
||||
$prefix_map = array();
|
||||
foreach ($prefixes as $prefix => $paths) {
|
||||
if (FALSE === strpos($prefix, '\\')) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$prefix_map[$logical_base_path][$deep_path] = $this->defaultBehavior;
|
||||
}
|
||||
}
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$namespace_map[$logical_base_path][$deep_path] = $this->psr0Behavior;
|
||||
}
|
||||
}
|
||||
if (!empty($prefix_map)) {
|
||||
$this->prefixMap->registerDeepPaths($prefix_map);
|
||||
}
|
||||
$this->namespaceMap->registerDeepPaths($namespace_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addMultiplePsr4(array $map) {
|
||||
$namespace_map = array();
|
||||
foreach ($map as $namespace => $paths) {
|
||||
$logical_base_path = Util::namespaceLogicalPath($namespace);
|
||||
foreach ($paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/'
|
||||
: '';
|
||||
$namespace_map[$logical_base_path][$deep_path] = $this->defaultBehavior;
|
||||
}
|
||||
}
|
||||
$this->namespaceMap->registerDeepPaths($namespace_map);
|
||||
}
|
||||
|
||||
// Composer ClassLoader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addClassMap(array $classMap) {
|
||||
$this->finder->registerClasses($classMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function add($prefix, $paths) {
|
||||
if (FALSE === strpos($prefix, '\\')) {
|
||||
// Due to the ambiguity of PSR-0, this could be either PEAR-like or namespaced.
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior);
|
||||
}
|
||||
}
|
||||
// Namespaced PSR-0
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->psr0Behavior);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPsr0($prefix, $paths) {
|
||||
$this->add($prefix, $paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPsr4($prefix, $paths) {
|
||||
// Namespaced PSR-4
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $deep_path) {
|
||||
$deep_path = strlen($deep_path)
|
||||
? rtrim($deep_path, '/') . '/'
|
||||
: '';
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior);
|
||||
}
|
||||
}
|
||||
|
||||
// More convenience stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addNamespacePsr0($prefix, $paths) {
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->psr0Behavior);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPear($prefix, $paths) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPearFlat($prefix, $paths) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $deep_path) {
|
||||
$deep_path = strlen($deep_path) ? (rtrim($deep_path, '/') . '/') : '';
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Adapter;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\CommonRegistrationInterface;
|
||||
|
||||
interface ClassFinderAdapterInterface extends CommonRegistrationInterface {
|
||||
|
||||
// Discovery
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* @param string[] $paths
|
||||
* File paths or wildcard paths for class discovery.
|
||||
*/
|
||||
function addClassmapSources($paths);
|
||||
|
||||
// Composer tools
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Scan a composer.json file provided by a Composer package.
|
||||
*
|
||||
* @param string $file
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
function composerJson($file);
|
||||
|
||||
/**
|
||||
* Scan a directory containing Composer-generated autoload files.
|
||||
*
|
||||
* @param string $dir
|
||||
* Directory to look for Composer-generated files. Typically this is the
|
||||
* ../vendor/composer dir.
|
||||
*/
|
||||
function composerDir($dir);
|
||||
|
||||
// multiple PSR-0 / PSR-4
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Add multiple PSR-0 namespaces
|
||||
*
|
||||
* @param array $prefixes
|
||||
*/
|
||||
function addMultiplePsr0(array $prefixes);
|
||||
|
||||
/**
|
||||
* Add multiple PSR-4 namespaces
|
||||
*
|
||||
* @param array $map
|
||||
*/
|
||||
function addMultiplePsr4(array $map);
|
||||
|
||||
}
|
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Adapter;
|
||||
|
||||
use Drupal\xautoload\DirectoryBehavior\DefaultDirectoryBehavior;
|
||||
use Drupal\xautoload\ClassFinder\ExtendedClassFinderInterface;
|
||||
use Drupal\xautoload\ClassFinder\Plugin\DrupalExtensionNamespaceFinderPlugin;
|
||||
use Drupal\xautoload\ClassFinder\Plugin\DrupalExtensionUnderscoreFinderPlugin;
|
||||
use Drupal\xautoload\DrupalSystem\DrupalSystemInterface;
|
||||
|
||||
/**
|
||||
* Service that knows how to register module namespaces and prefixes into the
|
||||
* class loader, and that remembers which modules have already been registered.
|
||||
*/
|
||||
class DrupalExtensionAdapter {
|
||||
|
||||
/**
|
||||
* @var \Drupal\xautoload\DrupalSystem\DrupalSystemInterface
|
||||
*/
|
||||
protected $system;
|
||||
|
||||
/**
|
||||
* @var ExtendedClassFinderInterface
|
||||
*/
|
||||
protected $finder;
|
||||
|
||||
/**
|
||||
* One finder plugin for each extension type ('module', 'theme').
|
||||
*
|
||||
* @var DrupalExtensionNamespaceFinderPlugin[]
|
||||
*/
|
||||
protected $namespaceBehaviors = array();
|
||||
|
||||
/**
|
||||
* One finder plugin for each extension type ('module', 'theme').
|
||||
*
|
||||
* @var DrupalExtensionUnderscoreFinderPlugin[]
|
||||
*/
|
||||
protected $prefixBehaviors = array();
|
||||
|
||||
/**
|
||||
* The namespace map used in the class loader.
|
||||
*
|
||||
* @var \Drupal\xautoload\ClassFinder\GenericPrefixMap
|
||||
*/
|
||||
protected $namespaceMap;
|
||||
|
||||
/**
|
||||
* The prefix map used in the class loader.
|
||||
*
|
||||
* @var \Drupal\xautoload\ClassFinder\GenericPrefixMap
|
||||
*/
|
||||
protected $prefixMap;
|
||||
|
||||
/**
|
||||
* Which modules have already been processed.
|
||||
*
|
||||
* @var bool[]
|
||||
*/
|
||||
protected $registered = array();
|
||||
|
||||
/**
|
||||
* Directory behavior for PSR-4
|
||||
*
|
||||
* @var DefaultDirectoryBehavior
|
||||
*/
|
||||
protected $defaultBehavior;
|
||||
|
||||
/**
|
||||
* @param DrupalSystemInterface $system
|
||||
* @param ExtendedClassFinderInterface $finder
|
||||
*/
|
||||
function __construct(DrupalSystemInterface $system, ExtendedClassFinderInterface $finder) {
|
||||
$this->system = $system;
|
||||
$this->finder = $finder;
|
||||
$this->namespaceMap = $finder->getNamespaceMap();
|
||||
$this->prefixMap = $finder->getPrefixMap();
|
||||
foreach (array('module', 'theme') as $extension_type) {
|
||||
$this->namespaceBehaviors[$extension_type] = new DrupalExtensionNamespaceFinderPlugin(
|
||||
$extension_type,
|
||||
$this->namespaceMap,
|
||||
$this->prefixMap,
|
||||
$this->system);
|
||||
$this->prefixBehaviors[$extension_type] = new DrupalExtensionUnderscoreFinderPlugin(
|
||||
$extension_type,
|
||||
$this->namespaceMap,
|
||||
$this->prefixMap,
|
||||
$this->system);
|
||||
}
|
||||
$this->defaultBehavior = new DefaultDirectoryBehavior();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register lazy plugins for enabled Drupal modules and themes, assuming that
|
||||
* we don't know yet whether they use PSR-0, PEAR-Flat, or none of these.
|
||||
*
|
||||
* @param string[] $extensions
|
||||
* An array where the keys are extension names, and the values are extension
|
||||
* types like 'module' or 'theme'.
|
||||
*/
|
||||
function registerExtensions(array $extensions) {
|
||||
|
||||
$prefix_map = array();
|
||||
$namespace_map = array();
|
||||
foreach ($extensions as $name => $type) {
|
||||
if (empty($this->namespaceBehaviors[$type])) {
|
||||
// Unsupported extension type, e.g. "theme_engine".
|
||||
// This can happen if a site was upgraded from Drupal 6.
|
||||
// See https://drupal.org/comment/8503979#comment-8503979
|
||||
continue;
|
||||
}
|
||||
if (!empty($this->registered[$name])) {
|
||||
// The extension has already been processed.
|
||||
continue;
|
||||
}
|
||||
$namespace_map['Drupal/' . $name . '/'][$name] = $this->namespaceBehaviors[$type];
|
||||
$prefix_map[str_replace('_', '/', $name) . '/'][$name] = $this->prefixBehaviors[$type];
|
||||
$this->registered[$name] = TRUE;
|
||||
}
|
||||
$this->namespaceMap->registerDeepPaths($namespace_map);
|
||||
$this->prefixMap->registerDeepPaths($prefix_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register lazy plugins for a given extension, assuming that we don't know
|
||||
* yet whether it uses PSR-0, PEAR-Flat, or none of these.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
*/
|
||||
function registerExtension($name, $type) {
|
||||
if (!empty($this->registered[$name])) {
|
||||
// The extension has already been processed.
|
||||
return;
|
||||
}
|
||||
$this->namespaceMap->registerDeepPath('Drupal/' . $name . '/', $name, $this->namespaceBehaviors[$type]);
|
||||
$this->prefixMap->registerDeepPath(str_replace('_', '/', $name) . '/', $name, $this->prefixBehaviors[$type]);
|
||||
$this->registered[$name] = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register PSR-4 directory for an extension.
|
||||
* Override previous settings for this extension.
|
||||
*
|
||||
* @param string $name
|
||||
* The extension name.
|
||||
* @param string $extension_dir
|
||||
* The directory of the extension.
|
||||
* @param string $subdir
|
||||
* The PSR-4 base directory, relative to the extension directory.
|
||||
* E.g. 'lib' or 'src'.
|
||||
*/
|
||||
function registerExtensionPsr4($name, $extension_dir, $subdir) {
|
||||
if (!empty($this->registered[$name])) {
|
||||
if ('psr-4' === $this->registered[$name]) {
|
||||
// It already happened.
|
||||
return;
|
||||
}
|
||||
// Unregister the lazy plugins.
|
||||
$this->namespaceMap->unregisterDeepPath('Drupal/' . $name . '/', $name);
|
||||
$this->prefixMap->unregisterDeepPath(str_replace('_', '/', $name) . '/', $name);
|
||||
}
|
||||
|
||||
$dir = strlen($subdir)
|
||||
? $extension_dir . '/' . trim($subdir, '/') . '/'
|
||||
: $extension_dir . '/';
|
||||
$this->namespaceMap->registerDeepPath('Drupal/' . $name . '/', $dir, $this->defaultBehavior);
|
||||
|
||||
// Re-add the PSR-0 test directory, for consistency's sake.
|
||||
if (is_dir($psr0_tests_dir = $extension_dir . '/lib/Drupal/' . $name . '/Tests')) {
|
||||
$this->namespaceMap->registerDeepPath('Drupal/' . $name . '/Tests/', $psr0_tests_dir, $this->defaultBehavior);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Adapter;
|
||||
|
||||
use Drupal\xautoload\Discovery\ComposerDir;
|
||||
use Drupal\xautoload\Discovery\ComposerJson;
|
||||
|
||||
/**
|
||||
* An instance of this class is passed around to implementations of
|
||||
* hook_xautoload(). It acts as a wrapper around the ClassFinder, to register
|
||||
* stuff.
|
||||
*/
|
||||
class LocalDirectoryAdapter implements ClassFinderAdapterInterface {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $localDirectory;
|
||||
|
||||
/**
|
||||
* @var ClassFinderAdapter
|
||||
*/
|
||||
protected $master;
|
||||
|
||||
/**
|
||||
* @param ClassFinderAdapter $adapter
|
||||
* The class finder object.
|
||||
* @param string $localDirectory
|
||||
*/
|
||||
function __construct(ClassFinderAdapter $adapter, $localDirectory) {
|
||||
// parent::__construct($adapter->finder, $adapter->getClassmapGenerator());
|
||||
$this->master = $adapter;
|
||||
$this->localDirectory = strlen($localDirectory)
|
||||
? rtrim($localDirectory, '/') . '/'
|
||||
: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an adapter object that is not relative to a local directory.
|
||||
*
|
||||
* @return ClassFinderAdapter
|
||||
*/
|
||||
function absolute() {
|
||||
return $this->master;
|
||||
}
|
||||
|
||||
// Discovery
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds source paths for classmap discovery.
|
||||
*
|
||||
* The classmap for each source will be cached between requests.
|
||||
* A "clear all caches" will trigger a rescan.
|
||||
*
|
||||
* @param string[] $paths
|
||||
* File paths or wildcard paths for class discovery.
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addClassmapSources($paths, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($paths);
|
||||
$this->master->addClassmapSources($paths);
|
||||
}
|
||||
|
||||
// Composer tools
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Scans a composer.json file provided by a Composer package.
|
||||
*
|
||||
* @param string $file
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
function composerJson($file, $relative = TRUE) {
|
||||
$relative && $file = $this->localDirectory . $file;
|
||||
$json = ComposerJson::createFromFile($file);
|
||||
$json->writeToAdapter($this->master);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans a directory containing Composer-generated autoload files.
|
||||
*
|
||||
* @param string $dir
|
||||
* Directory to look for Composer-generated files. Typically this is the
|
||||
* ../vendor/composer dir.
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function composerDir($dir, $relative = TRUE) {
|
||||
$relative && $dir = $this->localDirectory . $dir;
|
||||
$dir = ComposerDir::create($dir);
|
||||
$dir->writeToAdapter($this->master);
|
||||
}
|
||||
|
||||
// multiple PSR-0 / PSR-4
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds multiple PSR-0 prefixes.
|
||||
*
|
||||
* @param array $prefixes
|
||||
* Each array key is a PSR-0 prefix, e.g. "Acme\\FooPackage\\".
|
||||
* Each array value is either a PSR-0 base directory or an array of PSR-0
|
||||
* base directories.
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addMultiplePsr0(array $prefixes, $relative = TRUE) {
|
||||
$relative && $this->prependMultiple($prefixes);
|
||||
$this->master->addMultiplePsr0($prefixes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple PSR-4 namespaces.
|
||||
*
|
||||
* @param array $map
|
||||
* Each array key is a namespace, e.g. "Acme\\FooPackage\\".
|
||||
* Each array value is either a PSR-4 base directory or an array of PSR-4
|
||||
* base directories.
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addMultiplePsr4(array $map, $relative = TRUE) {
|
||||
$relative && $this->prependMultiple($map);
|
||||
$this->master->addMultiplePsr4($map);
|
||||
}
|
||||
|
||||
// Composer ClassLoader
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Registers an array ("map") of classes to file paths.
|
||||
*
|
||||
* @param array $classMap
|
||||
* The map of classes to file paths.
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addClassMap(array $classMap, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($classMap);
|
||||
$this->master->addClassMap($classMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PSR-0 style prefix. Alias for ->addPsr0().
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string|\string[] $paths
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function add($prefix, $paths, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($paths);
|
||||
$this->master->add($prefix, $paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PSR-0 style prefix. Alias for ->add().
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string|\string[] $paths
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addPsr0($prefix, $paths, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($paths);
|
||||
$this->master->add($prefix, $paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PSR-4 style namespace.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string|\string[] $paths
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addPsr4($prefix, $paths, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($paths);
|
||||
$this->master->addPsr4($prefix, $paths);
|
||||
}
|
||||
|
||||
// More convenience stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds a PSR-0 style namespace.
|
||||
*
|
||||
* This will assume that we are really dealing with a namespace, even if it
|
||||
* has no '\\' included.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string|\string[] $paths
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addNamespacePsr0($prefix, $paths, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($paths);
|
||||
$this->master->addNamespacePsr0($prefix, $paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a PEAR-like prefix.
|
||||
*
|
||||
* This will assume with no further checks that $prefix contains no namespace
|
||||
* separator.
|
||||
*
|
||||
* @param string $prefix
|
||||
* The prefix, e.g. 'Acme_FooPackage_'
|
||||
* @param string|string[] $paths
|
||||
* An array of paths, or one specific path.
|
||||
* E.g. 'lib' for $relative = TRUE,
|
||||
* or 'sites/all/libraries/AcmeFooPackage/lib' for $relative = FALSE.
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addPear($prefix, $paths, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($paths);
|
||||
$this->master->addPear($prefix, $paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a prefix similar to PEAR, but with flat directories.
|
||||
*
|
||||
* This will assume with no further checks that $prefix contains no namespace
|
||||
* separator.
|
||||
*
|
||||
* @param string $prefix
|
||||
* The prefix, e.g. 'Acme_FooPackage_'
|
||||
* @param string|string[] $paths
|
||||
* An array of paths, or one specific path.
|
||||
* E.g. 'lib' for $relative = TRUE,
|
||||
* or 'sites/all/libraries/AcmeFooPackage/lib' for $relative = FALSE.
|
||||
* @param bool $relative
|
||||
* If TRUE, the paths will be relative to $this->localDirectory.
|
||||
*/
|
||||
function addPearFlat($prefix, $paths, $relative = TRUE) {
|
||||
$relative && $this->prependToPaths($paths);
|
||||
$this->master->addPearFlat($prefix, $paths);
|
||||
}
|
||||
|
||||
// Relative path handling
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Prepends $this->localDirectory to a number of paths.
|
||||
*
|
||||
* @param array $map
|
||||
*/
|
||||
protected function prependMultiple(array &$map) {
|
||||
foreach ($map as &$paths) {
|
||||
$paths = (array) $paths;
|
||||
foreach ($paths as &$path) {
|
||||
$path = $this->localDirectory . $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepends $this->localDirectory to a number of paths.
|
||||
*
|
||||
* @param string|string[] &$paths
|
||||
*/
|
||||
protected function prependToPaths(&$paths) {
|
||||
if (!is_array($paths)) {
|
||||
$paths = $this->localDirectory . $paths;
|
||||
}
|
||||
else {
|
||||
foreach ($paths as &$path) {
|
||||
$path = $this->localDirectory . $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\CacheManager;
|
||||
|
||||
use Drupal\xautoload\DrupalSystem\DrupalSystemInterface;
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
class CacheManager {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* @var \Drupal\xautoload\DrupalSystem\DrupalSystemInterface
|
||||
*/
|
||||
protected $system;
|
||||
|
||||
/**
|
||||
* @var CacheManagerObserverInterface[]
|
||||
*/
|
||||
protected $observers = array();
|
||||
|
||||
/**
|
||||
* @param string $prefix
|
||||
* @param \Drupal\xautoload\DrupalSystem\DrupalSystemInterface $system
|
||||
*/
|
||||
protected function __construct($prefix, DrupalSystemInterface $system) {
|
||||
$this->prefix = $prefix;
|
||||
$this->system = $system;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method has side effects, so it is not the constructor.
|
||||
*
|
||||
* @param \Drupal\xautoload\DrupalSystem\DrupalSystemInterface $system
|
||||
*
|
||||
* @return CacheManager
|
||||
*/
|
||||
static function create(DrupalSystemInterface $system) {
|
||||
$prefix = $system->variableGet(XAUTOLOAD_VARNAME_CACHE_PREFIX, NULL);
|
||||
$manager = new self($prefix, $system);
|
||||
if (empty($prefix)) {
|
||||
$manager->renewCachePrefix();
|
||||
}
|
||||
return $manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CacheManagerObserverInterface $observer
|
||||
*/
|
||||
function observeCachePrefix($observer) {
|
||||
$observer->setCachePrefix($this->prefix);
|
||||
$this->observers[] = $observer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew the cache prefix, save it, and notify all observers.
|
||||
*/
|
||||
function renewCachePrefix() {
|
||||
$this->prefix = Util::randomString();
|
||||
$this->system->variableSet(XAUTOLOAD_VARNAME_CACHE_PREFIX, $this->prefix);
|
||||
foreach ($this->observers as $observer) {
|
||||
$observer->setCachePrefix($this->prefix);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\CacheManager;
|
||||
|
||||
interface CacheManagerObserverInterface {
|
||||
|
||||
/**
|
||||
* Set the APC prefix after a flush cache.
|
||||
*
|
||||
* @param string $prefix
|
||||
* A prefix for the storage key in APC.
|
||||
*/
|
||||
function setCachePrefix($prefix);
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\CacheMissObserver;
|
||||
|
||||
use Drupal\xautoload\ClassLoader\AbstractClassLoaderDecorator;
|
||||
|
||||
/**
|
||||
* Replaces the ProxyClassFinder in the ClassLoader with the real ClassLoader.
|
||||
*
|
||||
* xautoload has a number of cached class loaders, working with APC cache or
|
||||
* other key-value stores.
|
||||
*
|
||||
* The cached class loaders use the decorator pattern, and decorate a
|
||||
* ClassFinder object, that will only be consulted on a cache miss.
|
||||
*
|
||||
* xautoload will first give the ClassLoader a ProxyClassFinder that wraps the
|
||||
* real class loader. On the first cache miss, this ProxyClassFinder will
|
||||
* notify all subscribed CacheMissObserverInterface object.
|
||||
*
|
||||
* The job of this particular observer is to replace the ProxyClassFinder, once
|
||||
* it has done its job. Instead, the ClassLoader will get a reference ot the
|
||||
* real ClassLoader, saving the overhead of going through ProxyClassFinder each
|
||||
* time.
|
||||
*
|
||||
* @see ProxyClassFinder
|
||||
*/
|
||||
class CacheMissLoaderSetFinder implements CacheMissObserverInterface {
|
||||
|
||||
/**
|
||||
* @var AbstractClassLoaderDecorator
|
||||
*/
|
||||
protected $loader;
|
||||
|
||||
/**
|
||||
* @param AbstractClassLoaderDecorator $loader
|
||||
*/
|
||||
function __construct($loader) {
|
||||
$this->loader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function cacheMiss($finder) {
|
||||
$this->loader->setFinder($finder);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\CacheMissObserver;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\ExtendedClassFinderInterface;
|
||||
|
||||
/**
|
||||
* An operation that can be queued up to be performed on the class finder once
|
||||
* it is initialized.
|
||||
*
|
||||
* In an average request, with the APC cache or similar enabled, class-to-file
|
||||
* mappings will usually be loaded from the cache. The "real" class finder will
|
||||
* only be initialized if one of the classes is not in the cache.
|
||||
*
|
||||
* @see ProxyClassFinder
|
||||
*/
|
||||
interface CacheMissObserverInterface {
|
||||
|
||||
/**
|
||||
* Executes the operation.
|
||||
*
|
||||
* This method will only be called if and when the "real" class finder is
|
||||
* initialized.
|
||||
*
|
||||
* @param ExtendedClassFinderInterface $finder
|
||||
* The class finder.
|
||||
*/
|
||||
function cacheMiss($finder);
|
||||
}
|
@ -0,0 +1,468 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder;
|
||||
|
||||
use Drupal\xautoload\ClassLoader\AbstractClassLoader;
|
||||
use Drupal\xautoload\DirectoryBehavior\DefaultDirectoryBehavior;
|
||||
use Drupal\xautoload\DirectoryBehavior\Psr0DirectoryBehavior;
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
class ClassFinder extends AbstractClassLoader implements ExtendedClassFinderInterface {
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
*/
|
||||
protected $classes = array();
|
||||
|
||||
/**
|
||||
* @var GenericPrefixMap
|
||||
*/
|
||||
protected $prefixMap;
|
||||
|
||||
/**
|
||||
* @var GenericPrefixMap
|
||||
*/
|
||||
protected $namespaceMap;
|
||||
|
||||
/**
|
||||
* @var DefaultDirectoryBehavior
|
||||
*/
|
||||
protected $defaultBehavior;
|
||||
|
||||
/**
|
||||
* @var Psr0DirectoryBehavior
|
||||
*/
|
||||
protected $psr0Behavior;
|
||||
|
||||
function __construct() {
|
||||
$this->prefixMap = new GenericPrefixMap('_');
|
||||
$this->namespaceMap = new GenericPrefixMap('\\');
|
||||
$this->defaultBehavior = new DefaultDirectoryBehavior();
|
||||
$this->psr0Behavior = new Psr0DirectoryBehavior();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getPrefixMap() {
|
||||
return $this->prefixMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function getNamespaceMap() {
|
||||
return $this->namespaceMap;
|
||||
}
|
||||
|
||||
// Composer compatibility
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addClassMap(array $classMap) {
|
||||
$this->registerClasses($classMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function add($prefix, $paths) {
|
||||
if (FALSE === strpos($prefix, '\\')) {
|
||||
// Due to the ambiguity of PSR-0, this could be either PEAR-like or namespaced.
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior);
|
||||
}
|
||||
}
|
||||
// Namespaced PSR-0
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->psr0Behavior);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPsr0($prefix, $paths) {
|
||||
$this->add($prefix, $paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPsr4($prefix, $paths) {
|
||||
// Namespaced PSR-4
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $deep_path) {
|
||||
$deep_path = strlen($deep_path)
|
||||
? rtrim($deep_path, '/') . '/'
|
||||
: '';
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior);
|
||||
}
|
||||
}
|
||||
|
||||
// More convenience stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addNamespacePsr0($prefix, $paths) {
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->psr0Behavior);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPear($prefix, $paths) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function addPearFlat($prefix, $paths) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $deep_path) {
|
||||
$deep_path = strlen($deep_path)
|
||||
? (rtrim($deep_path, '/') . '/')
|
||||
: '';
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$this->defaultBehavior
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Class map stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerClass($class, $file_path) {
|
||||
$this->classes[$class][$file_path] = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerClasses($classes) {
|
||||
foreach ($classes as $class => $file_path) {
|
||||
$this->classes[$class][$file_path] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Prefix stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerPrefixRoot($prefix, $root_path, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$behavior);
|
||||
|
||||
if (strlen($prefix)) {
|
||||
// We assume that the class named $prefix is also found at this path.
|
||||
$filepath = substr($deep_path, 0, -1) . '.php';
|
||||
$this->registerClass($prefix, $filepath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerPrefixesRoot($map, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$deep_map = array();
|
||||
foreach ($map as $prefix => $root_path) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$deep_map[$logical_base_path][$deep_path] = $behavior;
|
||||
|
||||
// Register the class with name $prefix.
|
||||
if (strlen($prefix)) {
|
||||
$filepath = substr($deep_path, 0, -1) . '.php';
|
||||
$this->classes[$prefix][$filepath] = TRUE;
|
||||
}
|
||||
}
|
||||
$this->prefixMap->registerDeepPaths($deep_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerPrefixDeep($prefix, $deep_path, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$this->registerPrefixDeepLocation($prefix, $deep_path, $behavior);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerPrefixesDeep($map, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$deep_map = array();
|
||||
foreach ($map as $prefix => $deep_path) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
$deep_path = strlen($deep_path)
|
||||
? rtrim($deep_path, '/') . '/'
|
||||
: '';
|
||||
$deep_map[$logical_base_path][$deep_path] = $behavior;
|
||||
}
|
||||
$this->prefixMap->registerDeepPaths($deep_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerPrefixDeepLocation($prefix, $deep_path, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
$deep_path = strlen($deep_path)
|
||||
? rtrim($deep_path, '/') . '/'
|
||||
: '';
|
||||
$this->prefixMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$behavior);
|
||||
}
|
||||
|
||||
// Namespace stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerNamespaceRoot($namespace, $root_path, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$logical_base_path = Util::namespaceLogicalPath($namespace);
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$behavior);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerNamespacesRoot($map, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$deep_map = array();
|
||||
foreach ($map as $namespace => $root_path) {
|
||||
$logical_base_path = Util::namespaceLogicalPath($namespace);
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
$deep_map[$logical_base_path][$deep_path] = $behavior;
|
||||
}
|
||||
$this->namespaceMap->registerDeepPaths($deep_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerNamespaceDeep($namespace, $path, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$logical_base_path = Util::namespaceLogicalPath($namespace);
|
||||
$deep_path = strlen($path)
|
||||
? $path . '/'
|
||||
: '';
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$logical_base_path,
|
||||
$deep_path,
|
||||
$behavior);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerNamespacesDeep($map, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$deep_map = array();
|
||||
foreach ($map as $namespace => $deep_path) {
|
||||
$logical_base_path = Util::namespaceLogicalPath($namespace);
|
||||
$deep_path = strlen($deep_path)
|
||||
? rtrim($deep_path, '/') . '/'
|
||||
: '';
|
||||
$deep_map[$logical_base_path][$deep_path] = $behavior;
|
||||
}
|
||||
$this->namespaceMap->registerDeepPaths($deep_map);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function registerNamespaceDeepLocation($namespace, $path, $behavior = NULL) {
|
||||
if (!isset($behavior)) {
|
||||
$behavior = $this->defaultBehavior;
|
||||
}
|
||||
$namespace_path_fragment = Util::namespaceLogicalPath($namespace);
|
||||
$deep_path = strlen($path)
|
||||
? $path . '/'
|
||||
: '';
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$namespace_path_fragment,
|
||||
$deep_path,
|
||||
$behavior);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
|
||||
// Fix the behavior of some PHP versions that prepend '\\' to the class name.
|
||||
if ('\\' === $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
// First check if the literal class name is registered.
|
||||
if (!empty($this->classes[$class])) {
|
||||
foreach ($this->classes[$class] as $filepath => $true) {
|
||||
if (file_exists($filepath)) {
|
||||
require $filepath;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the class has a namespace.
|
||||
if (FALSE !== $pos = strrpos($class, '\\')) {
|
||||
|
||||
// Build the "logical path" based on PSR-4 replacement rules.
|
||||
$logical_path = str_replace('\\', '/', $class) . '.php';
|
||||
|
||||
return $this->namespaceMap->loadClass($class, $logical_path, $pos);
|
||||
}
|
||||
|
||||
// Build the "logical path" based on PEAR replacement rules.
|
||||
$pear_logical_path = str_replace('_', '/', $class) . '.php';
|
||||
|
||||
// Clean up surplus '/' resulting from duplicate underscores, or an
|
||||
// underscore at the beginning of the class.
|
||||
while (FALSE !== $pos = strrpos('/' . $pear_logical_path, '//')) {
|
||||
$pear_logical_path[$pos] = '_';
|
||||
}
|
||||
|
||||
// Check if the class has any underscore.
|
||||
$pos = strrpos($pear_logical_path, '/');
|
||||
|
||||
return $this->prefixMap->loadClass($class, $pear_logical_path, $pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function apiFindFile($api, $class) {
|
||||
|
||||
// Fix the behavior of some PHP versions that prepend '\\' to the class name.
|
||||
if ('\\' === $class[0]) {
|
||||
$class = substr($class, 1);
|
||||
}
|
||||
|
||||
// First check if the literal class name is registered.
|
||||
if (!empty($this->classes[$class])) {
|
||||
foreach ($this->classes[$class] as $filepath => $true) {
|
||||
if ($api->suggestFile($filepath)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the class has a namespace.
|
||||
if (FALSE !== $pos = strrpos($class, '\\')) {
|
||||
|
||||
// Build the "logical path" based on PSR-4 replacement rules.
|
||||
$logical_path = str_replace('\\', '/', $class) . '.php';
|
||||
|
||||
return $this->namespaceMap->apiFindFile($api, $logical_path, $pos);
|
||||
}
|
||||
|
||||
// Build the "logical path" based on PEAR replacement rules.
|
||||
$pear_logical_path = str_replace('_', '/', $class) . '.php';
|
||||
|
||||
// Clean up surplus '/' resulting from duplicate underscores, or an
|
||||
// underscore at the beginning of the class.
|
||||
while (FALSE !== $pos = strrpos('/' . $pear_logical_path, '//')) {
|
||||
$pear_logical_path[$pos] = '_';
|
||||
}
|
||||
|
||||
// Check if the class has any underscore.
|
||||
$pos = strrpos($pear_logical_path, '/');
|
||||
|
||||
return $this->prefixMap->apiFindFile($api, $pear_logical_path, $pos);
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder;
|
||||
|
||||
use Drupal\xautoload\ClassLoader\ClassLoaderInterface;
|
||||
|
||||
interface ClassFinderInterface extends ClassLoaderInterface {
|
||||
|
||||
/**
|
||||
* Finds the path to the file where the class is defined.
|
||||
*
|
||||
* @param \Drupal\xautoload\ClassFinder\InjectedApi\InjectedApiInterface $api
|
||||
* API object with a suggestFile() method.
|
||||
* We are supposed to call $api->suggestFile($file) with all suggestions we
|
||||
* can find, until it returns TRUE. Once suggestFile() returns TRUE, we stop
|
||||
* and return TRUE as well. The $file will be in the $api object, so we
|
||||
* don't need to return it.
|
||||
* @param string $class
|
||||
* The name of the class, with all namespaces prepended.
|
||||
* E.g. Some\Namespace\Some\Class
|
||||
*
|
||||
* @return TRUE|NULL
|
||||
* TRUE, if we found the file for the class.
|
||||
* That is, if the $api->suggestFile($file) method returned TRUE one time.
|
||||
* NULL, if we have no more suggestions.
|
||||
*/
|
||||
function apiFindFile($api, $class);
|
||||
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder;
|
||||
|
||||
/**
|
||||
* Class finder interface with additional registration methods.
|
||||
*/
|
||||
interface CommonRegistrationInterface {
|
||||
|
||||
// Composer compatibility
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Registers an array ("map") of classes to file paths.
|
||||
*
|
||||
* @param array $classMap
|
||||
* Class to filename map. E.g. $classMap['Acme\Foo'] = 'lib/Acme/Foo.php'
|
||||
*/
|
||||
function addClassMap(array $classMap);
|
||||
|
||||
/**
|
||||
* Adds a PSR-0 style prefix. Alias for ->addPsr0().
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string[]|string $paths
|
||||
*/
|
||||
function add($prefix, $paths);
|
||||
|
||||
/**
|
||||
* Adds a PSR-0 style prefix. Alias for ->add().
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string[]|string $paths
|
||||
*/
|
||||
function addPsr0($prefix, $paths);
|
||||
|
||||
/**
|
||||
* Adds a PSR-4 style namespace.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string[]|string $paths
|
||||
*/
|
||||
function addPsr4($prefix, $paths);
|
||||
|
||||
// More convenience stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Adds a PSR-0 style namespace.
|
||||
*
|
||||
* This will assume that we are really dealing with a namespace, even if it
|
||||
* has no '\\' included.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string[]|string $paths
|
||||
*/
|
||||
function addNamespacePsr0($prefix, $paths);
|
||||
|
||||
/**
|
||||
* Adds a PEAR-like prefix.
|
||||
*
|
||||
* This will assume with no further checks that $prefix contains no namespace
|
||||
* separator.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string[]|string $paths
|
||||
*/
|
||||
function addPear($prefix, $paths);
|
||||
|
||||
/**
|
||||
* Adds a prefix similar to PEAR, but with flat directories.
|
||||
*
|
||||
* This will assume with no further checks that $prefix contains no namespace
|
||||
* separator.
|
||||
*
|
||||
* @param string $prefix
|
||||
* @param string[]|string $paths
|
||||
*/
|
||||
function addPearFlat($prefix, $paths);
|
||||
|
||||
}
|
@ -0,0 +1,215 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder;
|
||||
|
||||
use Drupal\xautoload\DirectoryBehavior\DirectoryBehaviorInterface;
|
||||
|
||||
/**
|
||||
* Class finder interface with additional registration methods.
|
||||
*/
|
||||
interface ExtendedClassFinderInterface extends ClassFinderInterface, CommonRegistrationInterface {
|
||||
|
||||
/**
|
||||
* @return GenericPrefixMap
|
||||
*/
|
||||
function getPrefixMap();
|
||||
|
||||
/**
|
||||
* @return GenericPrefixMap
|
||||
*/
|
||||
function getNamespaceMap();
|
||||
|
||||
// Class map stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register a filepath for an individual class.
|
||||
*
|
||||
* @param string $class
|
||||
* The class, e.g. My_Class
|
||||
* @param string $file_path
|
||||
* The path, e.g. "../lib/My/Class.php".
|
||||
*/
|
||||
function registerClass($class, $file_path);
|
||||
|
||||
/**
|
||||
* Register an array ("map") of classes to file paths.
|
||||
*
|
||||
* @param string[] $classes
|
||||
* The map of classes to file paths.
|
||||
*/
|
||||
function registerClasses($classes);
|
||||
|
||||
// Prefix stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register a PEAR-style root path for a given class prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
* Prefix, e.g. "My_Prefix", for classes like "My_Prefix_SomeClass".
|
||||
* This does ALSO cover the class named "My_Prefix" itself.
|
||||
* @param string $root_path
|
||||
* Root path, e.g. "../lib" or "../src", so that classes can be placed e.g.
|
||||
* My_Prefix_SomeClass -> ../lib/My/Prefix/SomeClass.php
|
||||
* My_Prefix -> ../lib/My/Prefix.php
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerPrefixRoot($prefix, $root_path, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Register an array of PEAR-style deep paths for given class prefixes.
|
||||
*
|
||||
* Note:
|
||||
* This actually goes beyond PEAR style, because it also allows "shallow"
|
||||
* PEAR-like structures like
|
||||
* my_library_Some_Class -> (library dir)/src/Some/Class.php
|
||||
* instead of
|
||||
* my_library_Some_Class -> (library dir)/src/my/library/Some/Class.php
|
||||
* via
|
||||
* $finder->registerPrefixDeep('my_library', "$library_dir/src");
|
||||
*
|
||||
* @param string[] $map
|
||||
* Associative array, the keys are the prefixes, the values are the
|
||||
* directories.
|
||||
* This does NOT cover the class named $prefix itself.
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerPrefixesRoot($map, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Register a PEAR-style deep path for a given class prefix.
|
||||
*
|
||||
* Note:
|
||||
* This actually goes beyond PEAR style, because it also allows things like
|
||||
* my_library_Some_Class -> (library dir)/src/Some/Class.php
|
||||
* instead of
|
||||
* my_library_Some_Class -> (library dir)/src/my/library/Some/Class.php
|
||||
* via
|
||||
* $finder->registerPrefixDeep('my_library', "$library_dir/src");
|
||||
*
|
||||
* @param string $prefix
|
||||
* Prefix, e.g. "My_Prefix", for classes like "My_Prefix_SomeClass".
|
||||
* This does NOT cover the class named "My_Prefix" itself.
|
||||
* @param string $deep_path
|
||||
* The deep path, e.g. "../lib/My/Prefix", for classes placed in
|
||||
* My_Prefix_SomeClass -> ../lib/My/Prefix/SomeClass.php
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerPrefixDeep($prefix, $deep_path, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Register an array of PEAR-style deep paths for given class prefixes.
|
||||
*
|
||||
* Note:
|
||||
* This actually goes beyond PEAR style, because it also allows "shallow"
|
||||
* PEAR-like structures like
|
||||
* my_library_Some_Class -> (library dir)/src/Some/Class.php
|
||||
* instead of
|
||||
* my_library_Some_Class -> (library dir)/src/my/library/Some/Class.php
|
||||
* via
|
||||
* $finder->registerPrefixDeep('my_library', "$library_dir/src");
|
||||
*
|
||||
* @param string[] $map
|
||||
* Associative array, the keys are the prefixes, the values are the
|
||||
* directories.
|
||||
* This does NOT cover the class named $prefix itself.
|
||||
* @param \Drupal\xautoload\DirectoryBehavior\DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerPrefixesDeep($map, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Register a filesystem location for a given class prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
* The prefix, e.g. "My_Prefix"
|
||||
* @param string $deep_path
|
||||
* The deep filesystem location, e.g. "../lib/My/Prefix".
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerPrefixDeepLocation($prefix, $deep_path, $behavior = NULL);
|
||||
|
||||
// Namespace stuff
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Register a PSR-0 root folder for a given namespace.
|
||||
*
|
||||
* @param string $namespace
|
||||
* The namespace, e.g. "My\Namespace", to cover all classes within that,
|
||||
* e.g. My\Namespace\SomeClass, or My\Namespace\Xyz\SomeClass. This does not
|
||||
* cover the root-level class, e.g. My\Namespace
|
||||
* @param string $root_path
|
||||
* The deep path, e.g. "../lib", if classes reside in e.g.
|
||||
* My\Namespace\SomeClass -> ../lib/My/Namespace/SomeClass.php
|
||||
* @param \Drupal\xautoload\DirectoryBehavior\DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerNamespaceRoot($namespace, $root_path, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Register PSR-0 root folders for given namespaces.
|
||||
*
|
||||
* @param string[] $map
|
||||
* Associative array, the keys are the namespaces, the values are the
|
||||
* directories.
|
||||
* @param \Drupal\xautoload\DirectoryBehavior\DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerNamespacesRoot($map, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Alias for registerNamespaceDeepLocation()
|
||||
*
|
||||
* @param string $namespace
|
||||
* The namespace, e.g. "My\Namespace"
|
||||
* @param string $path
|
||||
* The deep path, e.g. "../lib/My/Namespace"
|
||||
* @param \Drupal\xautoload\DirectoryBehavior\DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerNamespaceDeep($namespace, $path, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Register a number of "deep" namespace directories at once.
|
||||
*
|
||||
* @param string[] $map
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
*/
|
||||
function registerNamespacesDeep($map, $behavior = NULL);
|
||||
|
||||
/**
|
||||
* Register a deep filesystem location for a given namespace.
|
||||
*
|
||||
* @param string $namespace
|
||||
* The namespace, e.g. "My\Namespace"
|
||||
* @param string $path
|
||||
* The deep path, e.g. "../lib/My/Namespace"
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
* If TRUE, then we are not sure if the directory at $path actually exists.
|
||||
* If during the process we find the directory to be nonexistent, we
|
||||
* unregister the path.
|
||||
*/
|
||||
function registerNamespaceDeepLocation($namespace, $path, $behavior = NULL);
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder;
|
||||
|
||||
use Drupal\xautoload\DirectoryBehavior\DirectoryBehaviorInterface;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\LoadClassInjectedAPI;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\InjectedApiInterface;
|
||||
use Drupal\xautoload\DirectoryBehavior\DefaultDirectoryBehavior;
|
||||
use xautoload_FinderPlugin_Interface;
|
||||
use Drupal\xautoload\DirectoryBehavior\Psr0DirectoryBehavior;
|
||||
|
||||
/**
|
||||
* Helper class for the class finder.
|
||||
* This is not part of ClassFinder, because we want to use the same logic for
|
||||
* namespaces (PSR-0) and prefixes (PEAR).
|
||||
*
|
||||
* This thing does not actually deal with class names, but with transformed
|
||||
* paths.
|
||||
*
|
||||
* Example A:
|
||||
* When looking for a class \Aaa\Bbb\Ccc_Ddd, the class finder will
|
||||
* 1. Determine that this class is within a namespace.
|
||||
* 2. Transform that into "Aaa/Bbb/Ccc/Ddd.php".
|
||||
* 3. Check if the namespace map evaluator has anything registered for
|
||||
* 3.1. "Aaa/Bbb/"
|
||||
* 3.2. "Aaa/"
|
||||
* 3.3. ""
|
||||
*
|
||||
* Example A:
|
||||
* When looking for a class Aaa_Bbb_Ccc, the class finder will
|
||||
* 1. Determine that this class is NOT within a namespace.
|
||||
* 2. Check if a file is explicitly registered for the class itself.
|
||||
* 3. Transform the class name into "Aaa/Bbb/Ccc.php".
|
||||
* 4. Check if the prefix map evaluator has anything registered for
|
||||
* 4.1. "Aaa/Bbb/"
|
||||
* 4.2. "Aaa/"
|
||||
* 4.3. ""
|
||||
*/
|
||||
class GenericPrefixMap {
|
||||
|
||||
/**
|
||||
* @var DirectoryBehaviorInterface[][]
|
||||
* Format: $[$logical_base_path][$deep_path] = $behavior
|
||||
*/
|
||||
protected $paths = array();
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* Either '\\' or '_'.
|
||||
*/
|
||||
protected $separator;
|
||||
|
||||
/**
|
||||
* @param string $separator
|
||||
*/
|
||||
function __construct($separator) {
|
||||
$this->separator = $separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a class file would be in
|
||||
* $psr0_root . '/' . $path_fragment . $path_suffix
|
||||
* then instead, we look in
|
||||
* $deep_path . $path_suffix
|
||||
*
|
||||
* @param string $logical_base_path
|
||||
* The would-be namespace path relative to PSR-0 root.
|
||||
* That is, the namespace with '\\' replaced by '/'.
|
||||
* @param string $deep_path
|
||||
* The filesystem location of the (PSR-0) subfolder for the given namespace.
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
* Behavior in this directory.
|
||||
*/
|
||||
function registerDeepPath($logical_base_path, $deep_path, $behavior) {
|
||||
$this->paths[$logical_base_path][$deep_path] = $behavior;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $logical_base_path
|
||||
* The would-be namespace path relative to PSR-0 root.
|
||||
* That is, the namespace with '\\' replaced by '/'.
|
||||
* @param string $deep_path
|
||||
* The filesystem location of the (PSR-0) subfolder for the given namespace.
|
||||
* @param DirectoryBehaviorInterface $behavior
|
||||
* Behavior in this directory.
|
||||
*/
|
||||
function prependDeepPath($logical_base_path, $deep_path, $behavior) {
|
||||
$this->paths[$logical_base_path]
|
||||
= isset($this->paths[$logical_base_path])
|
||||
? array($deep_path => $behavior) + $this->paths[$logical_base_path]
|
||||
: array($deep_path => $behavior);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a bunch of those paths ..
|
||||
*
|
||||
* @param array[] $map
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
function registerDeepPaths(array $map) {
|
||||
foreach ($map as $key => $paths) {
|
||||
if (isset($this->paths[$key])) {
|
||||
$paths += $this->paths[$key];
|
||||
}
|
||||
$this->paths[$key] = $paths;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a registered path mapping.
|
||||
*
|
||||
* @param string $logical_base_path
|
||||
* @param string $deep_path
|
||||
*/
|
||||
function unregisterDeepPath($logical_base_path, $deep_path) {
|
||||
unset($this->paths[$logical_base_path][$deep_path]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $logical_path
|
||||
* Class name translated into a logical path, either with PSR-4 or with PEAR
|
||||
* translation rules.
|
||||
* @param int|bool $lastpos
|
||||
* Position of the last directory separator in $logical_path.
|
||||
* FALSE, if there is no directory separator in $logical_path.
|
||||
*
|
||||
* @return bool|NULL
|
||||
* TRUE, if the class was found.
|
||||
*/
|
||||
function loadClass($class, $logical_path, $lastpos) {
|
||||
$pos = $lastpos;
|
||||
while (TRUE) {
|
||||
$logical_base_path = (FALSE === $pos)
|
||||
? ''
|
||||
: substr($logical_path, 0, $pos + 1);
|
||||
|
||||
if (isset($this->paths[$logical_base_path])) {
|
||||
foreach ($this->paths[$logical_base_path] as $dir => $behavior) {
|
||||
if ($behavior instanceof DefaultDirectoryBehavior) {
|
||||
// PSR-4 and PEAR
|
||||
if (file_exists($file = $dir . substr($logical_path, $pos + 1))) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
elseif ($behavior instanceof Psr0DirectoryBehavior) {
|
||||
// PSR-0
|
||||
if (file_exists(
|
||||
$file = $dir
|
||||
. substr($logical_path, $pos + 1, $lastpos - $pos)
|
||||
. str_replace('_', '/', substr($logical_path, $lastpos + 1))
|
||||
)) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
elseif ($behavior instanceof xautoload_FinderPlugin_Interface) {
|
||||
// Legacy "FinderPlugin".
|
||||
$api = new LoadClassInjectedAPI($class);
|
||||
if ($behavior->findFile($api, $logical_base_path, substr($logical_path, $pos + 1), $dir)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Continue with parent fragment.
|
||||
if (FALSE === $pos) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$pos = strrpos($logical_base_path, '/', -2);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the file for a class that in PSR-0 or PEAR would be in
|
||||
* $psr_0_root . '/' . $path_fragment . $path_suffix
|
||||
*
|
||||
* @param InjectedApiInterface $api
|
||||
* @param string $logical_path
|
||||
* Class name translated into a logical path, either with PSR-4 or with PEAR
|
||||
* translation rules.
|
||||
* @param int|bool $lastpos
|
||||
* Position of the last directory separator in $logical_path.
|
||||
* FALSE, if there is no directory separator in $logical_path.
|
||||
*
|
||||
* @return bool|NULL
|
||||
* TRUE, if the class was found.
|
||||
*/
|
||||
function apiFindFile($api, $logical_path, $lastpos) {
|
||||
$pos = $lastpos;
|
||||
while (TRUE) {
|
||||
$logical_base_path = (FALSE === $pos)
|
||||
? ''
|
||||
: substr($logical_path, 0, $pos + 1);
|
||||
|
||||
if (isset($this->paths[$logical_base_path])) {
|
||||
foreach ($this->paths[$logical_base_path] as $dir => $behavior) {
|
||||
if ($behavior instanceof DefaultDirectoryBehavior) {
|
||||
// PSR-4 and PEAR
|
||||
if ($api->suggestFile($dir . substr($logical_path, $pos + 1))) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
elseif ($behavior instanceof Psr0DirectoryBehavior) {
|
||||
// PSR-0
|
||||
if ($api->suggestFile(
|
||||
$dir
|
||||
. substr($logical_path, $pos + 1, $lastpos - $pos)
|
||||
. str_replace('_', '/', substr($logical_path, $lastpos + 1))
|
||||
)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
elseif ($behavior instanceof xautoload_FinderPlugin_Interface) {
|
||||
// Legacy "FinderPlugin".
|
||||
if ($behavior->findFile($api, $logical_base_path, substr($logical_path, $pos + 1), $dir)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Continue with parent fragment.
|
||||
if (FALSE === $pos) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
$pos = strrpos($logical_base_path, '/', -2);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\InjectedApi;
|
||||
|
||||
/**
|
||||
* To help testability, we use an injected API instead of just a return value.
|
||||
* The injected API can be mocked to provide a mocked file_exists(), and to
|
||||
* monitor all suggested candidates, not just the correct return value.
|
||||
*/
|
||||
abstract class AbstractInjectedApi implements InjectedApiInterface {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* The class name to look for. Set in the constructor.
|
||||
*/
|
||||
protected $className;
|
||||
|
||||
/**
|
||||
* @param $class_name
|
||||
* Name of the class or interface we are trying to load.
|
||||
*/
|
||||
function __construct($class_name) {
|
||||
$this->className = $class_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is done in the injected api object, so we can easily provide a mock
|
||||
* implementation.
|
||||
*/
|
||||
function is_dir($dir) {
|
||||
return is_dir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the class we are looking for.
|
||||
*
|
||||
* @return string
|
||||
* The class we are looking for.
|
||||
*/
|
||||
function getClass() {
|
||||
return $this->className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy method to force autoloading this class (or an ancestor).
|
||||
*/
|
||||
static function forceAutoload() {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\InjectedApi;
|
||||
|
||||
/**
|
||||
* To help testability, we use an injected API instead of just a return value.
|
||||
* The injected API can be mocked to provide a mocked file_exists(), and to
|
||||
* monitor all suggested candidates, not just the correct return value.
|
||||
*/
|
||||
class CollectFilesInjectedApi extends AbstractInjectedApi {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* The method that, if called with $this->file, will return TRUE.
|
||||
*/
|
||||
protected $methodName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* The file where $this->$method($this->file) will return TRUE.
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* @var array[]
|
||||
* All files that were suggested.
|
||||
*/
|
||||
protected $suggestions;
|
||||
|
||||
/**
|
||||
* @param string $class_name
|
||||
* @var string $method
|
||||
* The method that, if called with $this->file, will return TRUE.
|
||||
* @param string $file
|
||||
* The file where $this->$method($this->file) will return TRUE.
|
||||
*/
|
||||
function __construct($class_name, $method_name, $file) {
|
||||
$this->methodName = $method_name;
|
||||
$this->file = $file;
|
||||
parent::__construct($class_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* When the process has finished, use this to return the result.
|
||||
*
|
||||
* @return string
|
||||
* The file that is supposed to declare the class.
|
||||
*/
|
||||
function getSuggestions() {
|
||||
return $this->suggestions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggest a file that, if the file exists,
|
||||
* has to declare the class we are looking for.
|
||||
* Only keep the class on success.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return __FUNCTION__ === $this->methodName && $file === $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but skip the file_exists(),
|
||||
* assuming that we already know the file exists.
|
||||
*
|
||||
* This could make sense if a plugin already did the file_exists() check.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_skipFileExists($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but assume that file_exists() returns TRUE.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_checkNothing($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but check the full PHP include path.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile_checkIncludePath($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return __FUNCTION__ == $this->methodName && $file === $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessFile($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return __FUNCTION__ == $this->methodName && $file === $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessPath($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return __FUNCTION__ == $this->methodName && $file === $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimFile($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimPath($file) {
|
||||
$this->suggestions[] = array(__FUNCTION__, $file);
|
||||
return __FUNCTION__ == $this->methodName && $file === $this->file;
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\InjectedApi;
|
||||
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
/**
|
||||
* To help testability, we use an injected API instead of just a return value.
|
||||
* The injected API can be mocked to provide a mocked file_exists(), and to
|
||||
* monitor all suggested candidates, not just the correct return value.
|
||||
*/
|
||||
class FindFileInjectedApi extends AbstractInjectedApi {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* The file that was found.
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* When the process has finished, use this to return the result.
|
||||
*
|
||||
* @return string
|
||||
* The file that is supposed to declare the class.
|
||||
*/
|
||||
function getFile() {
|
||||
return $this->file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Suggest a file that, if the file exists,
|
||||
* has to declare the class we are looking for.
|
||||
* Only keep the class on success.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile($file) {
|
||||
if (file_exists($file)) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but skip the file_exists(),
|
||||
* assuming that we already know the file exists.
|
||||
*
|
||||
* This could make sense if a plugin already did the file_exists() check.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_skipFileExists($file) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but assume that file_exists() returns TRUE.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_checkNothing($file) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but check the full PHP include path.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile_checkIncludePath($file) {
|
||||
if (FALSE !== $file = Util::findFileInIncludePath($file)) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessFile($file) {
|
||||
// The file must be included, or else we can't know if it defines the class.
|
||||
require_once $file;
|
||||
if (Util::classIsDefined($this->className)) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessPath($file) {
|
||||
if (file_exists($file)) {
|
||||
// The file must be included, or else we can't know if it defines the class.
|
||||
require_once $file;
|
||||
if (Util::classIsDefined($this->className)) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimFile($file) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimPath($file) {
|
||||
if (file_exists($file)) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\InjectedApi;
|
||||
|
||||
/**
|
||||
* To help testability, we use an injected API instead of just a return value.
|
||||
* The injected API can be mocked to provide a mocked file_exists(), and to
|
||||
* monitor all suggested candidates, not just the correct return value.
|
||||
*/
|
||||
interface InjectedApiInterface {
|
||||
|
||||
/**
|
||||
* This is done in the injected api object, so we can easily provide a mock
|
||||
* implementation.
|
||||
*/
|
||||
function is_dir($dir);
|
||||
|
||||
/**
|
||||
* Get the name of the class we are looking for.
|
||||
*
|
||||
* @return string
|
||||
* The class we are looking for.
|
||||
*/
|
||||
function getClass();
|
||||
|
||||
/**
|
||||
* Suggest a file that, if the file exists,
|
||||
* has to declare the class we are looking for.
|
||||
* Only keep the class on success.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile($file);
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but skip the file_exists(),
|
||||
* assuming that we already know the file exists.
|
||||
*
|
||||
* This could make sense if a plugin already did the file_exists() check.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_skipFileExists($file);
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but assume that file_exists() returns TRUE.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_checkNothing($file);
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but check the full PHP include path.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile_checkIncludePath($file);
|
||||
|
||||
/**
|
||||
* Suggest a file that MUST exists, and that MAY declare the class we are
|
||||
* looking for.
|
||||
*
|
||||
* This is useful if a plugin already did the is_file() check by itself.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return boolean|NULL
|
||||
* TRUE, if we are not interested in further candidates.
|
||||
* FALSE|NULL, if we are interested in further candidates.
|
||||
*/
|
||||
function guessFile($file);
|
||||
|
||||
/**
|
||||
* Suggest a file that MAY exist, and that MAY declare the class we are
|
||||
* looking for.
|
||||
*
|
||||
* This is useful if a plugin already did the is_file() check by itself.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return boolean|NULL
|
||||
* TRUE, if we are not interested in further candidates.
|
||||
* FALSE|NULL, if we are interested in further candidates.
|
||||
*/
|
||||
function guessPath($file);
|
||||
|
||||
/**
|
||||
* Suggest a file that MUST exist, and if so, MUST declare the class we are
|
||||
* looking for.
|
||||
*
|
||||
* This is useful if a plugin already did the is_file() check by itself.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return boolean|NULL
|
||||
* TRUE, if we are not interested in further candidates.
|
||||
* FALSE|NULL, if we are interested in further candidates.
|
||||
*/
|
||||
function claimFile($file);
|
||||
|
||||
/**
|
||||
* Suggest a file that MAY exist, and if so, MUST declare the class we are
|
||||
* looking for.
|
||||
*
|
||||
* This is useful if a plugin already did the is_file() check by itself.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return boolean|NULL
|
||||
* TRUE, if we are not interested in further candidates.
|
||||
* FALSE|NULL, if we are interested in further candidates.
|
||||
*/
|
||||
function claimPath($file);
|
||||
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\InjectedApi;
|
||||
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
/**
|
||||
* To help testability, we use an injected API instead of just a return value.
|
||||
* The injected API can be mocked to provide a mocked file_exists(), and to
|
||||
* monitor all suggested candidates, not just the correct return value.
|
||||
*/
|
||||
class LoadClassGetFileInjectedApi extends FindFileInjectedApi {
|
||||
|
||||
/**
|
||||
* Suggest a file that, if the file exists,
|
||||
* has to declare the class we are looking for.
|
||||
* Only keep the class on success.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile($file) {
|
||||
if (file_exists($file)) {
|
||||
$this->file = $file;
|
||||
require $file;
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but skip the file_exists(),
|
||||
* assuming that we already know the file exists.
|
||||
*
|
||||
* This could make sense if a plugin already did the file_exists() check.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_skipFileExists($file) {
|
||||
$this->file = $file;
|
||||
require $file;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but assume that file_exists() returns TRUE.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file was found - which is always.
|
||||
*/
|
||||
function suggestFile_checkNothing($file) {
|
||||
$this->file = $file;
|
||||
require $file;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as suggestFile(), but check the full PHP include path.
|
||||
*
|
||||
* @param string $file
|
||||
* The file that is supposed to declare the class.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if the file exists.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function suggestFile_checkIncludePath($file) {
|
||||
if (FALSE !== $file = Util::findFileInIncludePath($file)) {
|
||||
$this->file = $file;
|
||||
require $file;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessFile($file) {
|
||||
require_once $file;
|
||||
if (Util::classIsDefined($this->className)) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessPath($file) {
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
if (Util::classIsDefined($this->className)) {
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimFile($file) {
|
||||
require $file;
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimPath($file) {
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
$this->file = $file;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\InjectedApi;
|
||||
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
/**
|
||||
* To help testability, we use an injected API instead of just a return value.
|
||||
* The injected API can be mocked to provide a mocked file_exists(), and to
|
||||
* monitor all suggested candidates, not just the correct return value.
|
||||
*/
|
||||
class LoadClassInjectedAPI extends AbstractInjectedApi {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function suggestFile($file) {
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function suggestFile_skipFileExists($file) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function suggestFile_checkNothing($file) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function suggestFile_checkIncludePath($file) {
|
||||
if (FALSE !== $file = Util::findFileInIncludePath($file)) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessFile($file) {
|
||||
require_once $file;
|
||||
|
||||
return Util::classIsDefined($this->className);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function guessPath($file) {
|
||||
if (file_exists($file)) {
|
||||
require_once $file;
|
||||
|
||||
return Util::classIsDefined($this->className);
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimFile($file) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function claimPath($file) {
|
||||
if (file_exists($file)) {
|
||||
require $file;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\Plugin;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\InjectedApiInterface;
|
||||
|
||||
/**
|
||||
* @see _registry_check_code()
|
||||
*/
|
||||
class DrupalCoreRegistryPlugin implements FinderPluginInterface {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $baseDir;
|
||||
|
||||
/**
|
||||
* @param string $baseDir
|
||||
*/
|
||||
function __construct($baseDir) {
|
||||
$this->baseDir = $baseDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the file for a class that in PSR-0 or PEAR would be in
|
||||
* $psr_0_root . '/' . $path_fragment . $path_suffix
|
||||
*
|
||||
* E.g.:
|
||||
* - The class we look for is Some\Namespace\Some\Class
|
||||
* - The file is actually in "exotic/location.php". This is not following
|
||||
* PSR-0 or PEAR standard, so we need a plugin.
|
||||
* -> The class finder will transform the class name to
|
||||
* "Some/Namespace/Some/Class.php"
|
||||
* - The plugin was registered for the namespace "Some\Namespace". This is
|
||||
* because all those exotic classes all begin with Some\Namespace\
|
||||
* -> The arguments will be:
|
||||
* ($api = the API object, see below)
|
||||
* $logical_base_path = "Some/Namespace/"
|
||||
* $relative_path = "Some/Class.php"
|
||||
* $api->getClass() gives the original class name, if we still need it.
|
||||
* -> We are supposed to:
|
||||
* if ($api->suggestFile('exotic/location.php')) {
|
||||
* return TRUE;
|
||||
* }
|
||||
*
|
||||
* @param InjectedApiInterface $api
|
||||
* An object with a suggestFile() method.
|
||||
* We are supposed to suggest files until suggestFile() returns TRUE, or we
|
||||
* have no more suggestions.
|
||||
* @param string $logical_base_path_empty
|
||||
* The key that this plugin was registered with.
|
||||
* With trailing '/'.
|
||||
* @param string $relative_path_irrelevant
|
||||
* Second part of the canonical path, ending with '.php'.
|
||||
*
|
||||
* @return bool|null
|
||||
* TRUE, if the file was found.
|
||||
* FALSE or NULL, otherwise.
|
||||
*/
|
||||
function findFile($api, $logical_base_path_empty, $relative_path_irrelevant) {
|
||||
$q = db_select('registry');
|
||||
// Use LIKE here to make the query case-insensitive.
|
||||
$q->condition('name', db_like($api->getClass()), 'LIKE');
|
||||
$q->addField('registry', 'filename');
|
||||
$stmt = $q->execute();
|
||||
while ($relative_path = $stmt->fetchField()) {
|
||||
$file = $this->baseDir . $relative_path;
|
||||
// Attention: The db_select() above can trigger the class loader for
|
||||
// classes and interfaces of the database layer. This can cause some files
|
||||
// to be included twice, if the file defines more than one class.
|
||||
// So we need to use require_once here, instead of require. That is, use
|
||||
// guessFile() instead of claimFile().
|
||||
if ($api->guessFile($file)) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\Plugin;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\GenericPrefixMap;
|
||||
use Drupal\xautoload\DirectoryBehavior\DefaultDirectoryBehavior;
|
||||
use Drupal\xautoload\DirectoryBehavior\Psr0DirectoryBehavior;
|
||||
use Drupal\xautoload\DrupalSystem\DrupalSystemInterface;
|
||||
|
||||
/**
|
||||
* There are different dimensions of state for each module:
|
||||
*
|
||||
* 1) Classes outside of Drupal\\$modulename\\Tests\\
|
||||
* a) We don't know yet whether these classes are using PSR-0, PSR-4,
|
||||
* PEAR-Flat, or none of these.
|
||||
* b) We know these classes use PSR-0 only.
|
||||
* c) We know these classes use PSR-4 only.
|
||||
* d) We know these classes use PEAR-Flat only.
|
||||
*
|
||||
* 2) Classes inside Drupal\\$modulename\\Tests\\
|
||||
* a) We don't know yet whether these classes are using PSR-0, PSR-4, or none
|
||||
* of these.
|
||||
* b) We know these classes all use PSR-0.
|
||||
* c) We know these classes all use PSR-4.
|
||||
*
|
||||
* Any combination of a state from (1) with a state from (2) is possible.
|
||||
*
|
||||
* The state could even change during the execution of the findClass() method,
|
||||
* due to another autoloader instance being fired during a file inclusion, e.g.
|
||||
* for a base class.
|
||||
*/
|
||||
class DrupalExtensionNamespaceFinderPlugin implements FinderPluginInterface {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* E.g. 'theme' or 'module'.
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* Namespace map used in the class finder for PSR-0/4-like mappings.
|
||||
*
|
||||
* @var GenericPrefixMap
|
||||
*/
|
||||
protected $namespaceMap;
|
||||
|
||||
/**
|
||||
* Prefix map used in the class finder for PEAR-like mappings.
|
||||
*
|
||||
* @var GenericPrefixMap
|
||||
*/
|
||||
protected $prefixMap;
|
||||
|
||||
/**
|
||||
* Directory behavior for PSR-4.
|
||||
*
|
||||
* @var DefaultDirectoryBehavior
|
||||
*/
|
||||
protected $defaultBehavior;
|
||||
|
||||
/**
|
||||
* Directory behavior with the special underscore handling for PSR-0.
|
||||
*
|
||||
* @var Psr0DirectoryBehavior
|
||||
*/
|
||||
protected $psr0Behavior;
|
||||
|
||||
/**
|
||||
* @var DrupalSystemInterface
|
||||
*/
|
||||
protected $system;
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* E.g. 'theme' or 'module'.
|
||||
* @param GenericPrefixMap $namespace_map
|
||||
* @param GenericPrefixMap $prefix_map
|
||||
* @param DrupalSystemInterface $system
|
||||
*/
|
||||
function __construct($type, $namespace_map, $prefix_map, $system) {
|
||||
$this->type = $type;
|
||||
$this->prefixMap = $prefix_map;
|
||||
$this->namespaceMap = $namespace_map;
|
||||
$this->defaultBehavior = new DefaultDirectoryBehavior();
|
||||
$this->psr0Behavior = new Psr0DirectoryBehavior();
|
||||
$this->system = $system;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks up a class starting with "Drupal\$extension_name\\".
|
||||
*
|
||||
* This plugin method will be called for every class beginning with
|
||||
* "Drupal\\$extension_name\\", as long as the plugin is registered for
|
||||
* $logical_base_path = 'Drupal/$extension_name/'.
|
||||
*
|
||||
* A similar plugin will is registered along with this one for the PEAR-FLAT
|
||||
* pattern, called for every class beginning with $modulename . '_'.
|
||||
*
|
||||
* The plugin will eventually unregister itself and its cousin, once it has
|
||||
* - determined the correct path for the module, and
|
||||
* - determined that the module is using either PSR-0 or PSR-4.
|
||||
* It does that by including the file candidate for PSR-0 and/or PSR-4 and
|
||||
* checking whether the class is now defined.
|
||||
*
|
||||
* The plugin will instead register a direct
|
||||
*
|
||||
* @param \Drupal\xautoload\ClassFinder\InjectedApi\InjectedApiInterface $api
|
||||
* An object with methods like suggestFile() and guessFile().
|
||||
* @param string $logical_base_path
|
||||
* The logical base path determined from the registered namespace.
|
||||
* E.g. 'Drupal/menupoly/'.
|
||||
* @param string $relative_path
|
||||
* Remaining part of the logical path following $logical_base_path.
|
||||
* E.g. 'FooNamespace/BarClass.php'.
|
||||
* @param string|null $extension_name
|
||||
* Second key that the plugin was registered with. Usually this would be the
|
||||
* physical base directory where we prepend the relative path to get the
|
||||
* file path. But in this case it is simply the extensions name.
|
||||
* E.g. 'menupoly'.
|
||||
*
|
||||
* @return bool|null
|
||||
* TRUE, if the file was found.
|
||||
* FALSE or NULL, otherwise.
|
||||
*/
|
||||
function findFile($api, $logical_base_path, $relative_path, $extension_name = NULL) {
|
||||
|
||||
$extension_file = $this->system->drupalGetFilename($this->type, $extension_name);
|
||||
if (empty($extension_file)) {
|
||||
// Extension does not exist, or is not installed.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$nspath = 'Drupal/' . $extension_name . '/';
|
||||
$testpath = $nspath . 'Tests/';
|
||||
$uspath = $extension_name . '/';
|
||||
$extension_dir = dirname($extension_file);
|
||||
$src = $extension_dir . '/src/';
|
||||
$lib_psr0 = $extension_dir . '/lib/Drupal/' . $extension_name . '/';
|
||||
$is_test_class = (0 === strpos($relative_path, 'Tests/'));
|
||||
|
||||
// Try PSR-4.
|
||||
if ($api->guessPath($src . $relative_path)) {
|
||||
if ($is_test_class) {
|
||||
// Register PSR-0 directory for "Drupal\\$modulename\\Tests\\"
|
||||
// This generally happens only once per module, because for subsequent
|
||||
// test classes the class will be found before this plugin is triggered.
|
||||
// However, for class_exists() with nonexistent test files, this line
|
||||
// will occur more than once.
|
||||
$this->namespaceMap->registerDeepPath($testpath, $src . 'Tests/', $this->defaultBehavior);
|
||||
// We found the class, but it is a test class, so it does not tell us
|
||||
// anything about whether non-test classes are in PSR-0 or PSR-4.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Register PSR-4 directory for "Drupal\\$modulename\\".
|
||||
$this->namespaceMap->registerDeepPath($nspath, $src, $this->defaultBehavior);
|
||||
|
||||
// Unregister the lazy plugins, including this one, for
|
||||
// "Drupal\\$modulename\\" and for $modulename . '_'.
|
||||
$this->namespaceMap->unregisterDeepPath($nspath, $extension_name);
|
||||
$this->prefixMap->unregisterDeepPath($uspath, $extension_name);
|
||||
|
||||
// Test classes in PSR-4 are already covered by the PSR-4 plugin we just
|
||||
// registered. But test classes in PSR-0 would slip through. So we check
|
||||
// if a separate behavior needs to be registered for those.
|
||||
if (is_dir($lib_psr0 . 'Tests/')) {
|
||||
$this->namespaceMap->registerDeepPath($testpath, $lib_psr0 . 'Tests/', $this->psr0Behavior);
|
||||
}
|
||||
|
||||
// The class was found, so return TRUE.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Build PSR-0 relative path.
|
||||
if (FALSE === $nspos = strrpos($relative_path, '/')) {
|
||||
// No namespace separators in $relative_path, so all underscores must be
|
||||
// replaced.
|
||||
$relative_path = str_replace('_', '/', $relative_path);
|
||||
}
|
||||
else {
|
||||
// Replace only those underscores in $relative_path after the last
|
||||
// namespace separator, from right to left. On average there is no or very
|
||||
// few of them, so this loop rarely iterates even once.
|
||||
while ($nspos < $uspos = strrpos($relative_path, '_')) {
|
||||
$relative_path[$uspos] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
// Try PSR-0
|
||||
if ($api->guessPath($lib_psr0 . $relative_path)) {
|
||||
if ($is_test_class) {
|
||||
// We know now that there are test classes using PSR-0.
|
||||
$this->namespaceMap->registerDeepPath($testpath, $lib_psr0 . 'Tests/', $this->psr0Behavior);
|
||||
// We found the class, but it is a test class, so it does not tell us
|
||||
// anything about whether non-test classes are in PSR-0 or PSR-4.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Unregister the lazy plugins, including this one.
|
||||
$this->namespaceMap->unregisterDeepPath($nspath, $extension_name);
|
||||
$this->prefixMap->unregisterDeepPath($uspath, $extension_name);
|
||||
|
||||
// Register PSR-0 for regular namespaced classes.
|
||||
$this->namespaceMap->registerDeepPath($nspath, $lib_psr0, $this->psr0Behavior);
|
||||
|
||||
// Test classes in PSR-0 are already covered by the PSR-0 plugin we just
|
||||
// registered. But test classes in PSR-4 would slip through. So we check
|
||||
// if a separate behavior needs to be registered for those.
|
||||
# if (is_dir($src . 'Tests/')) {
|
||||
# $this->namespaceMap->registerDeepPath($testpath, $src . 'Tests/', $this->psr0Behavior);
|
||||
# }
|
||||
|
||||
// The class was found, so return TRUE.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\Plugin;
|
||||
|
||||
class DrupalExtensionUnderscoreFinderPlugin extends DrupalExtensionNamespaceFinderPlugin {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function findFile($api, $logical_base_path, $relative_path, $extension_name = NULL) {
|
||||
|
||||
$extension_file = $this->system->drupalGetFilename($this->type, $extension_name);
|
||||
|
||||
if (empty($extension_file)) {
|
||||
// Extension does not exist, or is not installed.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$nspath = 'Drupal/' . $extension_name . '/';
|
||||
$testpath = $nspath . 'Tests/';
|
||||
$uspath = $extension_name . '/';
|
||||
$lib = dirname($extension_file) . '/lib/';
|
||||
$lib_psr0 = $lib . 'Drupal/' . $extension_name . '/';
|
||||
|
||||
// Try PEAR-Flat.
|
||||
if ($api->guessPath($lib . $relative_path)) {
|
||||
// Register PEAR-Flat.
|
||||
$this->prefixMap->registerDeepPath($uspath, $lib, $this->defaultBehavior);
|
||||
// Unregister the lazy plugins.
|
||||
$this->namespaceMap->unregisterDeepPath($nspath, $extension_name);
|
||||
$this->prefixMap->unregisterDeepPath($uspath, $extension_name);
|
||||
// See if there are PSR-0 or PSR-4 test classes.
|
||||
if (is_dir($lib_psr0 . 'Tests/')) {
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$testpath,
|
||||
$lib_psr0 . 'Tests/',
|
||||
$this->psr0Behavior);
|
||||
}
|
||||
if (is_dir($lib . 'Tests/')) {
|
||||
$this->namespaceMap->registerDeepPath(
|
||||
$testpath,
|
||||
$lib . 'Tests/',
|
||||
$this->defaultBehavior);
|
||||
}
|
||||
|
||||
// The class was found, so return TRUE.
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// The class was not found, so return FALSE.
|
||||
return FALSE;
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\Plugin;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\InjectedApiInterface;
|
||||
use xautoload_FinderPlugin_Interface;
|
||||
|
||||
|
||||
/**
|
||||
* X Autoload plugins are for:
|
||||
* - More exotic autoload patterns that are incompatible with PSR-0 or PEAR
|
||||
* - Situations where we don't want to register a ton of namespaces, and using
|
||||
* a plugin instead gives us performance benefits.
|
||||
*/
|
||||
interface FinderPluginInterface extends xautoload_FinderPlugin_Interface {
|
||||
|
||||
/**
|
||||
* Find the file for a class that in PSR-0 or PEAR would be in
|
||||
* $psr_0_root . '/' . $path_fragment . $path_suffix
|
||||
*
|
||||
* E.g.:
|
||||
* - The class we look for is Some\Namespace\Some\Class
|
||||
* - The file is actually in "exotic/location.php". This is not following
|
||||
* PSR-0 or PEAR standard, so we need a plugin.
|
||||
* -> The class finder will transform the class name to
|
||||
* "Some/Namespace/Some/Class.php"
|
||||
* - The plugin was registered for the namespace "Some\Namespace". This is
|
||||
* because all those exotic classes all begin with Some\Namespace\
|
||||
* -> The arguments will be:
|
||||
* ($api = the API object, see below)
|
||||
* $path_fragment = "Some/Namespace/"
|
||||
* $path_suffix = "Some/Class.php"
|
||||
* $api->getClass() gives the original class name, if we still need it.
|
||||
* -> We are supposed to:
|
||||
* if ($api->suggestFile('exotic/location.php')) {
|
||||
* return TRUE;
|
||||
* }
|
||||
*
|
||||
* @param InjectedApiInterface $api
|
||||
* An object with a suggestFile() method.
|
||||
* We are supposed to suggest files until suggestFile() returns TRUE, or we
|
||||
* have no more suggestions.
|
||||
* @param string $path_fragment
|
||||
* The key that this plugin was registered with.
|
||||
* With trailing '/'.
|
||||
* @param string $path_suffix
|
||||
* Second part of the canonical path, ending with '.php'.
|
||||
* @param int|string $id
|
||||
* Id under which the plugin was registered.
|
||||
* This may be a numeric id, or a string key.
|
||||
*
|
||||
* @return bool|null
|
||||
* TRUE, if the file was found.
|
||||
* FALSE, otherwise.
|
||||
*
|
||||
* NOTE:
|
||||
* The signature of this method has changed since the legacy base interface,
|
||||
* with a new optional parameter being added.
|
||||
* Due to a bug in PHP 5.3.0 - 5.3.8, redeclaring the method with the
|
||||
* modified signature would result in a fatal error in these PHP versions.
|
||||
* This is why the method is commented out.
|
||||
* The additional optional parameter can still be added in implementations.
|
||||
*/
|
||||
# function findFile($api, $path_fragment, $path_suffix, $id = NULL);
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder\Plugin;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\FindFileInjectedApi;
|
||||
|
||||
class Psr4FinderPlugin implements FinderPluginInterface {
|
||||
|
||||
/**
|
||||
* @param FindFileInjectedApi $api
|
||||
* An object with a suggestFile() method.
|
||||
* We are supposed to suggest files until suggestFile() returns TRUE, or we
|
||||
* have no more suggestions.
|
||||
* @param string $logical_base_path
|
||||
* The key that this plugin was registered with.
|
||||
* With trailing '/'.
|
||||
* @param string $relative_path
|
||||
* Second part of the canonical path, ending with '.php'.
|
||||
* @param int|string $base_dir
|
||||
* Id under which the plugin was registered.
|
||||
* This should be the PSR-4 base directory.
|
||||
*
|
||||
* @return bool|null
|
||||
* TRUE, if the file was found.
|
||||
* FALSE, otherwise.
|
||||
*/
|
||||
function findFile($api, $logical_base_path, $relative_path, $base_dir = NULL) {
|
||||
// The $relative_path has the replacements from PSR-0, which we don't want.
|
||||
// So we need to re-calculate it.
|
||||
$relative_classname = substr($api->getClass(), strlen($logical_base_path));
|
||||
$relative_path = str_replace('\\', '/', $relative_classname) . '.php';
|
||||
return $api->suggestFile($base_dir . '/' . $relative_path);
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassFinder;
|
||||
|
||||
use Drupal\xautoload\ClassLoader\AbstractClassLoader;
|
||||
use Drupal\xautoload\CacheMissObserver\CacheMissObserverInterface;
|
||||
|
||||
/**
|
||||
* A placeholder class finder. Used to postpone expensive operations until they
|
||||
* are actually needed.
|
||||
*/
|
||||
class ProxyClassFinder extends AbstractClassLoader implements ClassFinderInterface {
|
||||
|
||||
/**
|
||||
* @var ExtendedClassFinderInterface
|
||||
* The actual class finder.
|
||||
*/
|
||||
protected $finder;
|
||||
|
||||
/**
|
||||
* @var CacheMissObserverInterface[]
|
||||
* Operations to run when the actual finder is initialized.
|
||||
*/
|
||||
protected $cacheMissObservers = array();
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
protected $initialized = FALSE;
|
||||
|
||||
/**
|
||||
* @param ExtendedClassFinderInterface $finder
|
||||
*
|
||||
* @internal param \Drupal\xautoload\Adapter\DrupalExtensionAdapter $helper
|
||||
*/
|
||||
function __construct($finder) {
|
||||
$this->finder = $finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
$this->initFinder();
|
||||
$this->finder->loadClass($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function apiFindFile($api, $class) {
|
||||
$this->initFinder();
|
||||
|
||||
return $this->finder->apiFindFile($api, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CacheMissObserverInterface $observer
|
||||
*/
|
||||
function observeFirstCacheMiss($observer) {
|
||||
if (!$this->initialized) {
|
||||
$this->cacheMissObservers[] = $observer;
|
||||
}
|
||||
else {
|
||||
$observer->cacheMiss($this->finder);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassFinderInterface
|
||||
*/
|
||||
function getFinder() {
|
||||
$this->initFinder();
|
||||
|
||||
return $this->finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the finder and notify cache miss observers.
|
||||
*/
|
||||
protected function initFinder() {
|
||||
if (!$this->initialized) {
|
||||
$this->initialized = TRUE;
|
||||
foreach ($this->cacheMissObservers as $operation) {
|
||||
$operation->cacheMiss($this->finder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\CacheManager\CacheManagerObserverInterface;
|
||||
use Drupal\xautoload\ClassFinder\ClassFinderInterface;
|
||||
use Drupal\xautoload\CacheManager\CacheManager;
|
||||
|
||||
abstract class AbstractCachedClassLoader
|
||||
extends AbstractClassLoaderDecorator
|
||||
implements CacheManagerObserverInterface {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* This method has side effects, so it is not the constructor.
|
||||
*
|
||||
* @param ClassFinderInterface $finder
|
||||
* @param CacheManager $cacheManager
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
static function create($finder, $cacheManager) {
|
||||
/** @var self $loader */
|
||||
$loader = new static($finder);
|
||||
if (!$loader->checkRequirements()) {
|
||||
$class = get_class($loader);
|
||||
throw new CacheNotSupportedException("Unable to use $class, because the respetive PHP extension is not enabled.");
|
||||
}
|
||||
$cacheManager->observeCachePrefix($loader);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected abstract function checkRequirements();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function setCachePrefix($prefix) {
|
||||
$this->prefix = $prefix;
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
/**
|
||||
* Behaves mostly like the Symfony ClassLoader classes.
|
||||
*/
|
||||
abstract class AbstractClassLoader implements ClassLoaderInterface {
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param boolean $prepend
|
||||
* If TRUE, the loader will be prepended. Otherwise, it will be appended.
|
||||
*/
|
||||
function register($prepend = FALSE) {
|
||||
// http://www.php.net/manual/de/function.spl-autoload-register.php#107362
|
||||
// "when specifying the third parameter (prepend), the function will fail badly in PHP 5.2"
|
||||
if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
|
||||
spl_autoload_register(array($this, 'loadClass'), TRUE, $prepend);
|
||||
}
|
||||
elseif ($prepend) {
|
||||
$loaders = spl_autoload_functions();
|
||||
spl_autoload_register(array($this, 'loadClass'));
|
||||
foreach ($loaders as $loader) {
|
||||
spl_autoload_unregister($loader);
|
||||
spl_autoload_register($loader);
|
||||
}
|
||||
}
|
||||
else {
|
||||
spl_autoload_register(array($this, 'loadClass'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister from the spl autoload stack.
|
||||
*/
|
||||
function unregister() {
|
||||
spl_autoload_unregister(array($this, 'loadClass'));
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\ClassFinder\ClassFinderInterface;
|
||||
|
||||
/**
|
||||
* Behaves mostly like the Symfony ClassLoader classes.
|
||||
*/
|
||||
abstract class AbstractClassLoaderDecorator extends AbstractClassLoader {
|
||||
|
||||
/**
|
||||
* @var ClassFinderInterface
|
||||
*/
|
||||
protected $finder;
|
||||
|
||||
/**
|
||||
* @param ClassFinderInterface $finder
|
||||
* The object that does the actual class finding.
|
||||
*/
|
||||
protected function __construct($finder) {
|
||||
$this->finder = $finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the finder with another one.
|
||||
*
|
||||
* @param ClassFinderInterface $finder
|
||||
* The object that does the actual class finding.
|
||||
*/
|
||||
function setFinder($finder) {
|
||||
$this->finder = $finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
$this->finder->loadClass($class);
|
||||
}
|
||||
}
|
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\CacheManager\CacheManager;
|
||||
use Drupal\xautoload\CacheManager\CacheManagerObserverInterface;
|
||||
use Drupal\xautoload\ClassFinder\ClassFinderInterface;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\LoadClassGetFileInjectedApi;
|
||||
|
||||
/**
|
||||
* Bass class for cached class loader decorators where cache entries cannot be
|
||||
* written one by one, but have to be written all at once instead.
|
||||
*
|
||||
* Saving the cache immediately on every cache miss would be too expensive. On
|
||||
* the other hand, saving only at the end of the request might fail if the
|
||||
* request does not end properly, or if some classes are still loaded after the
|
||||
* end-of-process callback.
|
||||
*
|
||||
* The solution is an exponentially growing queue. Cache writing happens not on
|
||||
* every cache miss, but only on the 1st, 3rd, 7th, 15th, 31st, 63rd etc.
|
||||
*
|
||||
* This will result in a "hot" cache after a limited number of requests, and
|
||||
* with a limited number of cache write operations.
|
||||
*/
|
||||
abstract class AbstractQueuedCachedClassLoader
|
||||
extends AbstractClassLoaderDecorator
|
||||
implements CacheManagerObserverInterface {
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $nMax = 1;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $n = 0;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $toBeDeleted = array();
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $toBeAdded = array();
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $classFiles;
|
||||
|
||||
/**
|
||||
* This method has side effects, so it is not the constructor.
|
||||
*
|
||||
* @param ClassFinderInterface $finder
|
||||
* @param CacheManager $cacheManager
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
static function create($finder, $cacheManager) {
|
||||
/** @var self $loader */
|
||||
$loader = new static($finder);
|
||||
$cacheManager->observeCachePrefix($loader);
|
||||
|
||||
return $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
|
||||
// Look if the cache has anything for this class.
|
||||
if (isset($this->classFiles[$class])) {
|
||||
$file = $this->classFiles[$class];
|
||||
// The is_file() check may cost around 0.0045 ms per class file, but this
|
||||
// depends on your system of course.
|
||||
if (is_file($file)) {
|
||||
require $file;
|
||||
|
||||
return;
|
||||
}
|
||||
$this->toBeDeleted[$class] = $file;
|
||||
unset($this->classFiles[$class]);
|
||||
++$this->n;
|
||||
}
|
||||
|
||||
// Resolve cache miss.
|
||||
$api = new LoadClassGetFileInjectedApi($class);
|
||||
if ($this->finder->apiFindFile($api, $class)) {
|
||||
// Queue the result for the cache.
|
||||
$this->toBeAdded[$class]
|
||||
= $this->classFiles[$class]
|
||||
= $api->getFile();
|
||||
++$this->n;
|
||||
}
|
||||
|
||||
// Save the cache if enough has been queued up.
|
||||
if ($this->n >= $this->nMax) {
|
||||
$this->classFiles = $this->updateClassFiles($this->toBeAdded, $this->toBeDeleted);
|
||||
$this->toBeDeleted = array();
|
||||
$this->toBeAdded = array();
|
||||
$this->nMax *= 2;
|
||||
$this->n = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the new cache prefix after a flush cache.
|
||||
*
|
||||
* @param string $prefix
|
||||
* A prefix for the storage key in APC.
|
||||
*/
|
||||
function setCachePrefix($prefix) {
|
||||
$this->classFiles = $this->loadClassFiles($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function loadClassFiles($prefix);
|
||||
|
||||
/**
|
||||
* @param string[] $toBeAdded
|
||||
* @param string[] $toBeRemoved
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
abstract protected function updateClassFiles($toBeAdded, $toBeRemoved);
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\CacheManager\CacheManagerObserverInterface;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\LoadClassGetFileInjectedApi;
|
||||
|
||||
class ApcClassLoader extends AbstractCachedClassLoader implements CacheManagerObserverInterface {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkRequirements() {
|
||||
return extension_loaded('apc') && function_exists('apc_store');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
|
||||
// Look if the cache has anything for this class.
|
||||
if ($file = apc_fetch($this->prefix . $class)) {
|
||||
if (is_file($file)) {
|
||||
require $file;
|
||||
|
||||
return;
|
||||
}
|
||||
apc_delete($this->prefix . $class);
|
||||
}
|
||||
|
||||
// Resolve cache miss.
|
||||
$api = new LoadClassGetFileInjectedApi($class);
|
||||
if ($this->finder->apiFindFile($api, $class)) {
|
||||
apc_store($this->prefix . $class, $api->getFile());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\CacheManager\CacheManagerObserverInterface;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\LoadClassGetFileInjectedApi;
|
||||
|
||||
class ApcuClassLoader extends AbstractCachedClassLoader implements CacheManagerObserverInterface {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkRequirements() {
|
||||
return extension_loaded('apcu') && function_exists('apcu_store');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
|
||||
// Look if the cache has anything for this class.
|
||||
if ($file = \apcu_fetch($this->prefix . $class)) {
|
||||
if (is_file($file)) {
|
||||
require $file;
|
||||
|
||||
return;
|
||||
}
|
||||
\apcu_delete($this->prefix . $class);
|
||||
}
|
||||
|
||||
// Resolve cache miss.
|
||||
$api = new LoadClassGetFileInjectedApi($class);
|
||||
if ($this->finder->apiFindFile($api, $class)) {
|
||||
\apcu_store($this->prefix . $class, $api->getFile());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
class ApcuQueuedCachedClassLoader extends AbstractQueuedCachedClassLoader {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function loadClassFiles($prefix) {
|
||||
$this->prefix = $prefix;
|
||||
$cached = \apcu_fetch($this->prefix);
|
||||
|
||||
return !empty($cached)
|
||||
? $cached
|
||||
: array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $toBeAdded
|
||||
* @param string[] $toBeRemoved
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function updateClassFiles($toBeAdded, $toBeRemoved) {
|
||||
|
||||
$class_files = $toBeAdded;
|
||||
// Other requests may have already written to the cache, so we get an up to
|
||||
// date version.
|
||||
$cached = \apcu_fetch($this->prefix);
|
||||
if (!empty($cached)) {
|
||||
$class_files += $cached;
|
||||
foreach ($toBeRemoved as $class => $file) {
|
||||
if (isset($class_files[$class]) && $class_files[$class] === $file) {
|
||||
unset($class_files[$class]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
\apcu_store($this->prefix, $class_files);
|
||||
|
||||
return $class_files;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
class CacheNotSupportedException extends \Exception {}
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
/**
|
||||
* Behaves mostly like the Symfony ClassLoader classes.
|
||||
*/
|
||||
interface ClassLoaderInterface {
|
||||
|
||||
/**
|
||||
* Registers this instance as an autoloader.
|
||||
*
|
||||
* @param boolean $prepend
|
||||
* If TRUE, the loader will be prepended. Otherwise, it will be appended.
|
||||
*/
|
||||
function register($prepend = FALSE);
|
||||
|
||||
/**
|
||||
* Unregister this instance as an autoloader.
|
||||
*/
|
||||
function unregister();
|
||||
|
||||
/**
|
||||
* Callback for class loading. This will include ("require") the file found.
|
||||
*
|
||||
* @param string $class
|
||||
* The class to load.
|
||||
*/
|
||||
function loadClass($class);
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\CacheManager\CacheManager;
|
||||
use Drupal\xautoload\ClassFinder\ClassFinderInterface;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\LoadClassGetFileInjectedApi;
|
||||
|
||||
/**
|
||||
* A class loader decorator using Drupal's native db cache.
|
||||
*/
|
||||
class DbCacheClassLoader extends AbstractQueuedCachedClassLoader {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $cacheName;
|
||||
|
||||
/**
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function loadClassFiles($prefix) {
|
||||
$this->cacheName = 'xautoload_db_cache:' . $prefix;
|
||||
$cached = cache_get($this->cacheName);
|
||||
return isset($cached->data)
|
||||
? $cached->data
|
||||
: array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $toBeAdded
|
||||
* @param string[] $toBeRemoved
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function updateClassFiles($toBeAdded, $toBeRemoved) {
|
||||
|
||||
$class_files = $toBeAdded;
|
||||
// Other requests may have already written to the cache, so we get an up to
|
||||
// date version.
|
||||
$cached = cache_get($this->cacheName);
|
||||
if (isset($cached->data)) {
|
||||
$class_files += $cached->data;
|
||||
foreach ($toBeRemoved as $class => $file) {
|
||||
if (isset($class_files[$class]) && $class_files[$class] === $file) {
|
||||
unset($class_files[$class]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cache_set($this->cacheName, $class_files);
|
||||
|
||||
return $class_files;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\CacheManager\CacheManagerObserverInterface;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\LoadClassGetFileInjectedApi;
|
||||
|
||||
class WinCacheClassLoader extends AbstractCachedClassLoader implements CacheManagerObserverInterface {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkRequirements() {
|
||||
return extension_loaded('wincache')
|
||||
&& function_exists('wincache_ucache_get');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
|
||||
// Look if the cache has anything for this class.
|
||||
if ($file = wincache_ucache_get($this->prefix . $class)) {
|
||||
if (is_file($file)) {
|
||||
require $file;
|
||||
|
||||
return;
|
||||
}
|
||||
wincache_ucache_delete($this->prefix . $class);
|
||||
}
|
||||
|
||||
// Resolve cache miss.
|
||||
$api = new LoadClassGetFileInjectedApi($class);
|
||||
if ($this->finder->apiFindFile($api, $class)) {
|
||||
wincache_ucache_set($this->prefix . $class, $api->getFile());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\ClassLoader;
|
||||
|
||||
use Drupal\xautoload\CacheManager\CacheManagerObserverInterface;
|
||||
use Drupal\xautoload\ClassFinder\InjectedApi\LoadClassGetFileInjectedApi;
|
||||
|
||||
class XCacheClassLoader extends AbstractCachedClassLoader implements CacheManagerObserverInterface {
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkRequirements() {
|
||||
return extension_loaded('Xcache') && function_exists('xcache_isset');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
function loadClass($class) {
|
||||
|
||||
// Look if the cache has anything for this class.
|
||||
if (xcache_isset($this->prefix . $class)
|
||||
&& $file = xcache_get($this->prefix . $class)
|
||||
) {
|
||||
if (is_file($file)) {
|
||||
require $file;
|
||||
|
||||
return;
|
||||
}
|
||||
xcache_unset($this->prefix . $class);
|
||||
}
|
||||
|
||||
// Resolve cache miss.
|
||||
$api = new LoadClassGetFileInjectedApi($class);
|
||||
if ($this->finder->apiFindFile($api, $class)) {
|
||||
xcache_set($this->prefix . $class, $api->getFile());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\DIC;
|
||||
|
||||
/**
|
||||
* @see ServiceFactory
|
||||
*/
|
||||
class ServiceContainer implements ServiceContainerInterface {
|
||||
|
||||
/**
|
||||
* @var ServiceFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* @var object[]
|
||||
*/
|
||||
protected $services = array();
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function get($key) {
|
||||
return isset($this->services[$key])
|
||||
? $this->services[$key]
|
||||
: $this->services[$key] = $this->factory->$key($this) ? : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the service for a specific key.
|
||||
*
|
||||
* @param string $key
|
||||
*/
|
||||
function reset($key) {
|
||||
$this->services[$key] = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new service under the given key.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $service
|
||||
*/
|
||||
function set($key, $service) {
|
||||
$this->services[$key] = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Magic getter for a service.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
function __get($key) {
|
||||
if (isset($this->services[$key])) {
|
||||
return $this->services[$key];
|
||||
}
|
||||
if (!method_exists($this->factory, $key)) {
|
||||
throw new \Exception("Unsupported key '$key' for service factory.");
|
||||
}
|
||||
|
||||
return $this->services[$key] = $this->factory->$key($this) ? : FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceFactory $factory
|
||||
*/
|
||||
function __construct($factory) {
|
||||
$this->factory = $factory;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
namespace Drupal\xautoload\DIC;
|
||||
|
||||
use Drupal\xautoload\Adapter\ClassFinderAdapter;
|
||||
use Drupal\xautoload\Adapter\DrupalExtensionAdapter;
|
||||
use Drupal\xautoload\ClassFinder\ExtendedClassFinderInterface;
|
||||
use Drupal\xautoload\CacheManager\CacheManager;
|
||||
use Drupal\xautoload\ClassFinder\ProxyClassFinder;
|
||||
use Drupal\xautoload\Discovery\ClassMapGenerator;
|
||||
use Drupal\xautoload\Discovery\ClassMapGeneratorInterface;
|
||||
use Drupal\xautoload\DrupalSystem\DrupalSystemInterface;
|
||||
use Drupal\xautoload\Libraries\LibrariesInfoAlter;
|
||||
use Drupal\xautoload\Phases\DrupalPhaseControl;
|
||||
use Drupal\xautoload\Phases\ExtensionNamespaces;
|
||||
use Drupal\xautoload\Main;
|
||||
|
||||
/**
|
||||
* @property Main $main
|
||||
* @property ClassFinderAdapter $adapter
|
||||
* @property ClassMapGeneratorInterface $classMapGenerator
|
||||
* @property ClassMapGenerator $classMapGeneratorRaw
|
||||
* @property CacheManager $cacheManager
|
||||
* @property ProxyClassFinder $proxyFinder
|
||||
* @property ExtendedClassFinderInterface $classFinder
|
||||
* @property ExtendedClassFinderInterface $finder
|
||||
* Alias for ->classFinder
|
||||
* @property DrupalSystemInterface $system
|
||||
* @property DrupalPhaseControl $phaseControl
|
||||
* @property DrupalExtensionAdapter $extensionRegistrationService
|
||||
* @property ExtensionNamespaces extensionNamespaces
|
||||
* @property LibrariesInfoAlter librariesInfoAlter
|
||||
*
|
||||
* @see \Drupal\xautoload\DIC\ServiceContainer
|
||||
* @see \Drupal\xautoload\DIC\ServiceFactory
|
||||
*/
|
||||
interface ServiceContainerInterface {
|
||||
|
||||
/**
|
||||
* Retrieves a lazy-instantiated service.
|
||||
*
|
||||
* @param string $key
|
||||
* A key to specify a service.
|
||||
* @return mixed
|
||||
* The service for the given key. Usually an object.
|
||||
*/
|
||||
function __get($key);
|
||||
}
|
174
frontend/drupal/modules/xautoload/src/DIC/ServiceFactory.php
Normal file
174
frontend/drupal/modules/xautoload/src/DIC/ServiceFactory.php
Normal file
@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\DIC;
|
||||
|
||||
use Drupal\xautoload\Adapter\ClassFinderAdapter;
|
||||
use Drupal\xautoload\Adapter\DrupalExtensionAdapter;
|
||||
use Drupal\xautoload\ClassFinder\ClassFinder;
|
||||
use Drupal\xautoload\ClassFinder\ClassFinderInterface;
|
||||
use Drupal\xautoload\CacheManager\CacheManager;
|
||||
use Drupal\xautoload\ClassFinder\ProxyClassFinder;
|
||||
use Drupal\xautoload\Discovery\CachedClassMapGenerator;
|
||||
use Drupal\xautoload\Discovery\ClassMapGenerator;
|
||||
use Drupal\xautoload\DrupalSystem\DrupalSystem;
|
||||
use Drupal\xautoload\DrupalSystem\DrupalSystemInterface;
|
||||
use Drupal\xautoload\Libraries\LibrariesInfoAlter;
|
||||
use Drupal\xautoload\Phases\DrupalCoreRegistryRegistrator;
|
||||
use Drupal\xautoload\Phases\DrupalPhaseControl;
|
||||
use Drupal\xautoload\Phases\ExtensionNamespaces;
|
||||
use Drupal\xautoload\Phases\HookXautoload;
|
||||
use Drupal\xautoload\Libraries\LibrariesOnInit;
|
||||
use Drupal\xautoload\Main;
|
||||
|
||||
/**
|
||||
* @see ServiceContainerInterface
|
||||
* @see ServiceContainer
|
||||
*/
|
||||
class ServiceFactory {
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return Main
|
||||
*/
|
||||
function main($services) {
|
||||
return new Main($services);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return ClassFinderAdapter
|
||||
*/
|
||||
function adapter($services) {
|
||||
return new ClassFinderAdapter($services->finder, $services->classMapGenerator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return ClassMapGenerator
|
||||
*/
|
||||
function classMapGenerator($services) {
|
||||
return new CachedClassMapGenerator($services->classMapGeneratorRaw, $services->system);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return ClassMapGenerator
|
||||
*/
|
||||
function classMapGeneratorRaw($services) {
|
||||
return new ClassMapGenerator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return DrupalExtensionAdapter
|
||||
*/
|
||||
function extensionRegistrationService($services) {
|
||||
return new DrupalExtensionAdapter($services->system, $services->finder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return CacheManager
|
||||
*/
|
||||
function cacheManager($services) {
|
||||
return CacheManager::create($services->system);
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy class finder.
|
||||
*
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return ClassFinderInterface
|
||||
* Proxy object wrapping the class finder.
|
||||
* This is used to delay namespace registration until the first time the
|
||||
* finder is actually used.
|
||||
* (which might never happen thanks to the APC cache)
|
||||
*/
|
||||
function proxyFinder($services) {
|
||||
// The class finder is cheap to create, so it can use an identity proxy.
|
||||
return new ProxyClassFinder($services->finder);
|
||||
}
|
||||
|
||||
/**
|
||||
* The class finder (alias for 'finder').
|
||||
*
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return ClassFinderInterface
|
||||
* Object that can find classes,
|
||||
* and provides methods to register namespaces and prefixes.
|
||||
* Note: The findClass() method expects an InjectedAPI argument.
|
||||
*/
|
||||
function classFinder($services) {
|
||||
return $services->finder;
|
||||
}
|
||||
|
||||
/**
|
||||
* The class finder (alias for 'classFinder').
|
||||
*
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return ClassFinderInterface
|
||||
* Object that can find classes,
|
||||
* and provides methods to register namespaces and prefixes.
|
||||
* Notes:
|
||||
* - The findClass() method expects an InjectedAPI argument.
|
||||
* - namespaces are only supported since PHP 5.3
|
||||
*/
|
||||
function finder($services) {
|
||||
return new ClassFinder();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return DrupalSystemInterface
|
||||
*/
|
||||
function system($services) {
|
||||
return new DrupalSystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return DrupalPhaseControl
|
||||
*/
|
||||
function phaseControl($services) {
|
||||
$observers = array(
|
||||
$services->extensionNamespaces,
|
||||
new HookXautoload($services->system),
|
||||
new LibrariesOnInit($services->system),
|
||||
);
|
||||
if ($services->system->variableGet(XAUTOLOAD_VARNAME_REPLACE_CORE, FALSE)) {
|
||||
$observers[] = new DrupalCoreRegistryRegistrator();
|
||||
}
|
||||
return new DrupalPhaseControl($services->system, $observers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return ExtensionNamespaces
|
||||
*/
|
||||
function extensionNamespaces($services) {
|
||||
return new ExtensionNamespaces($services->system);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ServiceContainer $services
|
||||
*
|
||||
* @return LibrariesInfoAlter
|
||||
*/
|
||||
function librariesInfoAlter($services) {
|
||||
return new LibrariesInfoAlter();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\DirectoryBehavior;
|
||||
|
||||
/**
|
||||
* Directory behavior for PSR-4 and PEAR.
|
||||
*
|
||||
* This class is a marker only, to be checked with instanceof.
|
||||
* @see \Drupal\xautoload\ClassFinder\GenericPrefixMap::loadClass()
|
||||
*/
|
||||
final class DefaultDirectoryBehavior implements DirectoryBehaviorInterface {
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\DirectoryBehavior;
|
||||
|
||||
interface DirectoryBehaviorInterface {
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\DirectoryBehavior;
|
||||
|
||||
/**
|
||||
* Directory behavior for PSR-0.
|
||||
*
|
||||
* This class is a marker only, to be checked with instanceof.
|
||||
* @see \Drupal\xautoload\ClassFinder\GenericPrefixMap::loadClass()
|
||||
*/
|
||||
final class Psr0DirectoryBehavior implements DirectoryBehaviorInterface {
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
class CachedClassMapGenerator implements ClassMapGeneratorInterface {
|
||||
|
||||
/**
|
||||
* @var ClassMapGeneratorInterface
|
||||
*/
|
||||
protected $decorated;
|
||||
|
||||
/**
|
||||
* @var \Drupal\xautoload\DrupalSystem\DrupalSystemInterface
|
||||
*/
|
||||
protected $system;
|
||||
|
||||
/**
|
||||
* @param ClassMapGeneratorInterface $decorated
|
||||
* @param \Drupal\xautoload\DrupalSystem\DrupalSystemInterface $system
|
||||
*/
|
||||
function __construct($decorated, $system) {
|
||||
$this->decorated = $decorated;
|
||||
$this->system = $system;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $paths
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
function wildcardPathsToClassmap($paths) {
|
||||
// Attempt to load from cache.
|
||||
$cid = 'xautoload:wildcardPathsToClassmap:' . md5(serialize($paths));
|
||||
$cache = $this->system->cacheGet($cid);
|
||||
if ($cache && isset($cache->data)) {
|
||||
return $cache->data;
|
||||
}
|
||||
// Resolve cache miss and save.
|
||||
$map = $this->decorated->wildcardPathsToClassmap($paths);
|
||||
$this->system->cacheSet($cid, $map);
|
||||
|
||||
return $map;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
class ClassMapGenerator implements ClassMapGeneratorInterface {
|
||||
|
||||
/**
|
||||
* @param string[] $paths
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
function wildcardPathsToClassmap($paths) {
|
||||
$files = $this->wildcardPathsToFiles($paths);
|
||||
|
||||
return $this->filesToClassmap($files);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $files
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function filesToClassmap($files) {
|
||||
$map = array();
|
||||
foreach ($files as $file) {
|
||||
$classes = FileInspector::inspectPhpFile($file);
|
||||
foreach ($classes as $class) {
|
||||
$map[$class] = $file;
|
||||
}
|
||||
}
|
||||
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $paths
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function wildcardPathsToFiles($paths) {
|
||||
$wildcardFinder = new WildcardFileFinder();
|
||||
$wildcardFinder->addPaths($paths);
|
||||
|
||||
return $wildcardFinder->getFiles();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
interface ClassMapGeneratorInterface {
|
||||
|
||||
/**
|
||||
* @param string[] $paths
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
function wildcardPathsToClassmap($paths);
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
use Drupal\xautoload\Adapter\ClassFinderAdapter;
|
||||
|
||||
class ComposerDir {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $dir;
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
static function create($dir) {
|
||||
if (!is_dir($dir)) {
|
||||
throw new \Exception("Composer directory '$dir' does not exist.");
|
||||
}
|
||||
return new self($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
*/
|
||||
protected function __construct($dir) {
|
||||
$this->dir = $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassFinderAdapter $adapter
|
||||
*/
|
||||
function writeToAdapter($adapter) {
|
||||
|
||||
// PSR-0 namespaces / prefixes
|
||||
if (is_file($this->dir . '/autoload_namespaces.php')) {
|
||||
$prefixes = require $this->dir . '/autoload_namespaces.php';
|
||||
if (!empty($prefixes)) {
|
||||
$adapter->addMultiplePsr0($prefixes);
|
||||
}
|
||||
}
|
||||
|
||||
// PSR-4 namespaces
|
||||
if (is_file($this->dir . '/autoload_psr4.php')) {
|
||||
$map = require $this->dir . '/autoload_psr4.php';
|
||||
if (!empty($map)) {
|
||||
$adapter->addMultiplePsr4($map);
|
||||
}
|
||||
}
|
||||
|
||||
// Class map
|
||||
if (is_file($this->dir . '/autoload_classmap.php')) {
|
||||
$class_map = require $this->dir . '/autoload_classmap.php';
|
||||
if (!empty($class_map)) {
|
||||
$adapter->addClassMap($class_map);
|
||||
}
|
||||
}
|
||||
|
||||
// Include path
|
||||
if (is_file($this->dir . '/include_paths.php')) {
|
||||
$include_paths = require $this->dir . '/include_paths.php';
|
||||
if (!empty($include_paths)) {
|
||||
array_push($include_paths, get_include_path());
|
||||
set_include_path(join(PATH_SEPARATOR, $include_paths));
|
||||
}
|
||||
}
|
||||
|
||||
// Include files
|
||||
if (is_file($this->dir . '/autoload_files.php')) {
|
||||
$include_files = require $this->dir . '/autoload_files.php';
|
||||
foreach ($include_files as $file) {
|
||||
require $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
132
frontend/drupal/modules/xautoload/src/Discovery/ComposerJson.php
Normal file
132
frontend/drupal/modules/xautoload/src/Discovery/ComposerJson.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
use Drupal\xautoload\Adapter\ClassFinderAdapter;
|
||||
|
||||
class ComposerJson {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $pathPrefix;
|
||||
|
||||
/**
|
||||
* @param string $file
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
static function createFromFile($file) {
|
||||
if (!file_exists($file)) {
|
||||
throw new \Exception("File '$file' does not exist.");
|
||||
}
|
||||
$json = file_get_contents($file);
|
||||
$data = json_decode($json, TRUE);
|
||||
if (NULL === $data && JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new \Exception("Invalid json in '$file'.");
|
||||
}
|
||||
return self::createFromData($data, dirname($file) . '/');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param string $path_prefix
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
static function createFromData($data, $path_prefix) {
|
||||
return empty($data['target-dir'])
|
||||
? new self($data, $path_prefix)
|
||||
: new ComposerJsonTargetDir($data, $path_prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param string $path_prefix
|
||||
*/
|
||||
protected function __construct(array $data, $path_prefix) {
|
||||
$this->data = $data;
|
||||
$this->pathPrefix = $path_prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassFinderAdapter $adapter
|
||||
*/
|
||||
function writeToAdapter(ClassFinderAdapter $adapter) {
|
||||
|
||||
$data = $this->data;
|
||||
|
||||
if (!empty($data['include-path'])) {
|
||||
$this->addIncludePaths((array)$data['include-path']);
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['psr-0'])) {
|
||||
$map = $this->transformMultiple($data['autoload']['psr-0']);
|
||||
$adapter->addMultiplePsr0($map);
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['psr-4'])) {
|
||||
$map = $this->transformMultiple($data['autoload']['psr-4']);
|
||||
$adapter->addMultiplePsr4($map);
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['classmap'])) {
|
||||
$this->addClassmapSources($adapter, (array)$data['autoload']['classmap']);
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['files'])) {
|
||||
foreach ($data['autoload']['files'] as $file) {
|
||||
require $this->pathPrefix . $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $multiple
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
protected function transformMultiple(array $multiple) {
|
||||
foreach ($multiple as &$paths) {
|
||||
$paths = (array)$paths;
|
||||
foreach ($paths as &$path) {
|
||||
if ('' === $path || '/' !== $path[0]) {
|
||||
$path = $this->pathPrefix . $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $multiple;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $include_paths
|
||||
*/
|
||||
protected function addIncludePaths(array $include_paths) {
|
||||
foreach ($include_paths as &$path) {
|
||||
$path = $this->pathPrefix . $path;
|
||||
}
|
||||
array_push($include_paths, get_include_path());
|
||||
set_include_path(join(PATH_SEPARATOR, $include_paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassFinderAdapter $adapter
|
||||
* @param string[] $sources_raw
|
||||
* Array of files and folders to scan for class implementations.
|
||||
*/
|
||||
protected function addClassmapSources($adapter, array $sources_raw) {
|
||||
foreach ($sources_raw as &$path) {
|
||||
$path = $this->pathPrefix . $path;
|
||||
}
|
||||
$adapter->addClassmapSources($sources_raw);
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
use Drupal\xautoload\Adapter\ClassFinderAdapter;
|
||||
use Drupal\xautoload\DirectoryBehavior\DefaultDirectoryBehavior;
|
||||
use Drupal\xautoload\DirectoryBehavior\Psr0DirectoryBehavior;
|
||||
use Drupal\xautoload\Util;
|
||||
|
||||
class ComposerJsonTargetDir extends ComposerJson {
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $targetDir;
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param string $path_prefix
|
||||
*/
|
||||
function __construct(array $data, $path_prefix) {
|
||||
parent::__construct($data, $path_prefix);
|
||||
$this->targetDir = rtrim($data['target-dir'], '/') . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassFinderAdapter $adapter
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
function writeToAdapter(ClassFinderAdapter $adapter) {
|
||||
|
||||
$data = $this->data;
|
||||
|
||||
if (!empty($data['include-path'])) {
|
||||
$paths = $this->pathsResolveTargetDir((array) $data['include-path']);
|
||||
$this->addIncludePaths($paths, $this->pathPrefix);
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['psr-0'])) {
|
||||
$this->addMultipleWithTargetDir($adapter, $data['autoload']['psr-0']);
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['psr-4'])) {
|
||||
throw new \Exception("PSR-4 is incompatible with target-dir.");
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['classmap'])) {
|
||||
$paths = $this->pathsResolveTargetDir($data['autoload']['classmap']);
|
||||
$this->addClassmapSources($adapter, $paths);
|
||||
}
|
||||
|
||||
if (!empty($data['autoload']['files'])) {
|
||||
$paths = $this->pathsResolveTargetDir($data['autoload']['files']);
|
||||
foreach ($paths as $file) {
|
||||
require $this->pathPrefix . $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $paths
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
protected function pathsResolveTargetDir(array $paths) {
|
||||
$strlen = strlen($this->targetDir);
|
||||
foreach ($paths as &$path) {
|
||||
if (0 === strpos($path, $this->targetDir)) {
|
||||
$path = substr($path, $strlen);
|
||||
}
|
||||
}
|
||||
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassFinderAdapter $adapter
|
||||
* @param array $prefixes
|
||||
*/
|
||||
protected function addMultipleWithTargetDir(ClassFinderAdapter $adapter, array $prefixes) {
|
||||
$default_behavior = new DefaultDirectoryBehavior();
|
||||
$psr0_behavior = new Psr0DirectoryBehavior();
|
||||
$namespace_map = array();
|
||||
$prefix_map = array();
|
||||
$target_dir_strlen = strlen($this->targetDir);
|
||||
foreach ($prefixes as $prefix => $paths) {
|
||||
if (FALSE === strpos($prefix, '\\')) {
|
||||
$logical_base_path = Util::prefixLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
if (0 !== strpos($deep_path, $this->targetDir)) {
|
||||
continue;
|
||||
}
|
||||
$deep_path = $this->pathPrefix . substr($deep_path, $target_dir_strlen);
|
||||
$prefix_map[$logical_base_path][$deep_path] = $default_behavior;
|
||||
}
|
||||
}
|
||||
$logical_base_path = Util::namespaceLogicalPath($prefix);
|
||||
foreach ((array) $paths as $root_path) {
|
||||
$deep_path = strlen($root_path)
|
||||
? rtrim($root_path, '/') . '/' . $logical_base_path
|
||||
: $logical_base_path;
|
||||
if (0 !== strpos($deep_path, $this->targetDir)) {
|
||||
continue;
|
||||
}
|
||||
$deep_path = $this->pathPrefix . substr($deep_path, $target_dir_strlen);
|
||||
$namespace_map[$logical_base_path][$deep_path] = $psr0_behavior;
|
||||
}
|
||||
}
|
||||
if (!empty($prefix_map)) {
|
||||
$adapter->getPrefixMap()->registerDeepPaths($prefix_map);
|
||||
}
|
||||
$adapter->getNamespaceMap()->registerDeepPaths($namespace_map);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
class FileInspector {
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @return string[]
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
static function inspectPhpFile($path) {
|
||||
try {
|
||||
$contents = php_strip_whitespace($path);
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(
|
||||
'Could not scan for classes inside ' . $path . ": \n" . $e->getMessage(),
|
||||
// The Exception code. Defaults to 0.
|
||||
0,
|
||||
// The previous exception used for exception chaining.
|
||||
$e);
|
||||
}
|
||||
|
||||
return self::inspectFileContents($contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $contents
|
||||
* The PHP file contents obtained with php_strip_whitespace($path).
|
||||
*
|
||||
* @return string[]
|
||||
* Classes discovered in the file.
|
||||
*/
|
||||
protected static function inspectFileContents($contents) {
|
||||
$traits = version_compare(PHP_VERSION, '5.4', '<')
|
||||
? ''
|
||||
: '|trait';
|
||||
|
||||
// return early if there is no chance of matching anything in this file
|
||||
if (!preg_match('{\b(?:class|interface' . $traits . ')\s}i', $contents)) {
|
||||
return array();
|
||||
}
|
||||
|
||||
// strip heredocs/nowdocs
|
||||
$contents = preg_replace(
|
||||
'{<<<\'?(\w+)\'?(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\1(?=\r\n|\n|\r|;)}s',
|
||||
'null',
|
||||
$contents);
|
||||
|
||||
// strip strings
|
||||
$contents = preg_replace(
|
||||
'{"[^"\\\\]*(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]*(\\\\.[^\'\\\\]*)*\'}s',
|
||||
'null',
|
||||
$contents);
|
||||
|
||||
// strip leading non-php code if needed
|
||||
if (substr($contents, 0, 2) !== '<?') {
|
||||
$contents = preg_replace('{^.+?<\?}s', '<?', $contents);
|
||||
}
|
||||
|
||||
// strip non-php blocks in the file
|
||||
$contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
|
||||
|
||||
// strip trailing non-php code if needed
|
||||
$pos = strrpos($contents, '?>');
|
||||
if (FALSE !== $pos && FALSE === strpos(substr($contents, $pos), '<?')) {
|
||||
$contents = substr($contents, 0, $pos);
|
||||
}
|
||||
|
||||
preg_match_all(
|
||||
'{
|
||||
(?:
|
||||
\b(?<![\$:>])(?P<type>class|interface' . $traits . ') \s+ (?P<name>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)
|
||||
| \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\s+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\s*\\\\\s*[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*)? \s*[\{;]
|
||||
)
|
||||
}ix',
|
||||
$contents,
|
||||
$matches
|
||||
);
|
||||
|
||||
$classes = array();
|
||||
$namespace = '';
|
||||
|
||||
for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
|
||||
if (!empty($matches['ns'][$i])) {
|
||||
$namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i])
|
||||
. '\\';
|
||||
}
|
||||
else {
|
||||
$classes[] = ltrim($namespace . $matches['name'][$i], '\\');
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is autoloaded with the regular uncached xautoload.
|
||||
*/
|
||||
|
||||
|
||||
namespace Drupal\xautoload\Discovery;
|
||||
|
||||
/**
|
||||
* Scan directories for wildcard files[] instructions in a module's info file.
|
||||
*/
|
||||
class WildcardFileFinder {
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* Info array for the wildcard string currently being processed.
|
||||
* This value changes for each new wildcard being processed.
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* @var mixed[]
|
||||
* $files array passed to hook_registry_files_alter().
|
||||
*/
|
||||
protected $files = array();
|
||||
|
||||
/**
|
||||
* @param array $paths
|
||||
* Array keys are file paths or wildcard file paths.
|
||||
*/
|
||||
function addDrupalPaths(array $paths) {
|
||||
foreach ($paths as $path => $value) {
|
||||
if (1
|
||||
&& FALSE !== strpos($path, '*')
|
||||
&& preg_match('#^([^\*]*)/(.*\*.*)$#', $path, $m)
|
||||
) {
|
||||
// Resolve wildcards.
|
||||
$this->value = $value;
|
||||
list(, $base, $wildcard) = $m;
|
||||
$this->scanDirectory($base, $wildcard);
|
||||
}
|
||||
else {
|
||||
// Register the file directly.
|
||||
$this->files[$path] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $paths
|
||||
* Array keys are file paths or wildcard file paths.
|
||||
* @param mixed $value
|
||||
*/
|
||||
function addPaths(array $paths, $value = TRUE) {
|
||||
foreach ($paths as $path) {
|
||||
if (1
|
||||
&& FALSE !== strpos($path, '*')
|
||||
&& preg_match('#^([^\*]*)/(.*\*.*)$#', $path, $m)
|
||||
) {
|
||||
// Resolve wildcards.
|
||||
$this->value = $value;
|
||||
list(, $base, $wildcard) = $m;
|
||||
$this->scanDirectory($base, $wildcard);
|
||||
}
|
||||
elseif (is_dir($path)) {
|
||||
// Resolve wildcards.
|
||||
$this->value = $value;
|
||||
$this->scanDirectory($path . '/', '**/*.inc');
|
||||
$this->scanDirectory($path . '/', '**/*.php');
|
||||
}
|
||||
elseif (is_file($path)) {
|
||||
// Register the file directly.
|
||||
$this->files[$path] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
function getFiles() {
|
||||
return array_keys($this->files);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
function getDrupalFiles() {
|
||||
return $this->files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
* Base folder, e.g. "sites/all/modules/foo/includes", which does NOT
|
||||
* contain any asterisk ("*").
|
||||
* @param string $wildcard
|
||||
* Suffix which may contain asterisks.
|
||||
*/
|
||||
protected function scanDirectory($dir, $wildcard) {
|
||||
if (!is_dir($dir)) {
|
||||
return;
|
||||
}
|
||||
if (FALSE === strpos($wildcard, '*')) {
|
||||
// $wildcard is a fixed string, not a wildcard.
|
||||
$this->suggestFile($dir . '/' . $wildcard);
|
||||
}
|
||||
elseif ('**' === $wildcard) {
|
||||
// Trick: "$a/**" == union of "$a/*" and "$a/*/**"
|
||||
$this->scanDirectoryLevel($dir, '*');
|
||||
$this->scanDirectoryLevel($dir, '*', '**');
|
||||
}
|
||||
elseif ('**/' === substr($wildcard, 0, 3)) {
|
||||
// Trick: "$a/**/$b" == union of "$a/$b" and "$a/*/**/$b"
|
||||
$remaining = substr($wildcard, 3);
|
||||
$this->scanDirectory($dir, $remaining);
|
||||
$this->scanDirectoryLevel($dir, '*', $wildcard);
|
||||
}
|
||||
elseif (FALSE !== ($slashpos = strpos($wildcard, '/'))) {
|
||||
// $wildcard consists of more than one fragment.
|
||||
$fragment = substr($wildcard, 0, $slashpos);
|
||||
$remaining = substr($wildcard, $slashpos + 1);
|
||||
if (FALSE === strpos($fragment, '*')) {
|
||||
$this->scanDirectory($dir . '/' . $fragment, $remaining);
|
||||
}
|
||||
else {
|
||||
$this->scanDirectoryLevel($dir, $fragment, $remaining);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// $wildcard represents a file name.
|
||||
$this->scanDirectoryLevel($dir, $wildcard);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
* Base directory, not containing any wildcard.
|
||||
* @param string $fragment
|
||||
* Wildcard path fragment to be processed now. This is never '**', but it
|
||||
* always contains at least one asterisk.
|
||||
* @param null $remaining
|
||||
* Optional rest of the wildcard string, that may contain path fragments to
|
||||
* be processed later.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function scanDirectoryLevel($dir, $fragment, $remaining = NULL) {
|
||||
|
||||
if (!is_dir($dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ('**' === $fragment) {
|
||||
throw new \Exception("Fragment must not be '**'.");
|
||||
}
|
||||
|
||||
foreach (scandir($dir) as $candidate) {
|
||||
if (!$this->validateCandidate($candidate, $fragment)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($remaining)) {
|
||||
$this->suggestFile($dir . '/' . $candidate);
|
||||
}
|
||||
else {
|
||||
$this->scanDirectory($dir . '/' . $candidate, $remaining);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $candidate
|
||||
* String to be checked against the wildcard.
|
||||
* @param $wildcard
|
||||
* Wildcard string like '*', '*.*' or '*.inc'.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE, if $candidate matches $wildcard.
|
||||
*/
|
||||
protected function validateCandidate($candidate, $wildcard) {
|
||||
|
||||
if ($candidate == '.' || $candidate == '..') {
|
||||
return FALSE;
|
||||
}
|
||||
if (strpos($candidate, '*') !== FALSE) {
|
||||
return FALSE;
|
||||
}
|
||||
if ($wildcard == '*' || $wildcard == '**') {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// More complex wildcard string.
|
||||
$fragments = array();
|
||||
foreach (explode('*', $wildcard) as $fragment) {
|
||||
$fragments[] = preg_quote($fragment);
|
||||
}
|
||||
$regex = implode('.*', $fragments);
|
||||
|
||||
return preg_match("/^$regex$/", $candidate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* Add a new file path to $this->filesInRegistry().
|
||||
*/
|
||||
protected function suggestFile($path) {
|
||||
if (is_file($path)) {
|
||||
$this->files[$path] = $this->value;
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user