Merge branch 'master' of github.com:CatoTH/friendica-addons
This commit is contained in:
commit
715a7db9f6
|
@ -1,8 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
$a = get_app();
|
||||||
|
$uri = parse_url($a->get_baseurl());
|
||||||
|
$path = "";
|
||||||
|
if (strlen($uri["path"]) > 1) {
|
||||||
|
$path = $uri["path"] . "/";
|
||||||
|
}
|
||||||
|
|
||||||
define("CALDAV_SQL_DB", "");
|
define("CALDAV_SQL_DB", "");
|
||||||
define("CALDAV_SQL_PREFIX", "dav_");
|
define("CALDAV_SQL_PREFIX", "dav_");
|
||||||
define("CALDAV_URL_PREFIX", "dav/");
|
define("CALDAV_URL_PREFIX", $path . "dav/");
|
||||||
|
|
||||||
define("CALDAV_NAMESPACE_PRIVATE", 1);
|
define("CALDAV_NAMESPACE_PRIVATE", 1);
|
||||||
define("CALDAV_NAMESPACE_FRIENDICA_NATIVE", 2);
|
define("CALDAV_NAMESPACE_FRIENDICA_NATIVE", 2);
|
||||||
|
|
|
@ -480,7 +480,7 @@ function wdcal_get_list_range_params($day, $weekstartday, $num_days, $type)
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function wdcal_print_feed()
|
function wdcal_print_feed($base_path = "")
|
||||||
{
|
{
|
||||||
$user_id = dav_compat_get_curr_user_id();
|
$user_id = dav_compat_get_curr_user_id();
|
||||||
$cals = array();
|
$cals = array();
|
||||||
|
@ -538,7 +538,7 @@ function wdcal_print_feed()
|
||||||
$ret['error'] = null;
|
$ret['error'] = null;
|
||||||
|
|
||||||
foreach ($cals as $c) {
|
foreach ($cals as $c) {
|
||||||
$events = $c->listItemsByRange($date[0], $date[1]);
|
$events = $c->listItemsByRange($date[0], $date[1], $base_path);
|
||||||
$ret["events"] = array_merge($ret["events"], $events);
|
$ret["events"] = array_merge($ret["events"], $events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,9 +113,10 @@ abstract class AnimexxCalSource
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param string $sd
|
* @param string $sd
|
||||||
* @param string $ed
|
* @param string $ed
|
||||||
|
* @param string $base_path
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public abstract function listItemsByRange($sd, $ed);
|
public abstract function listItemsByRange($sd, $ed, $base_path);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,4 +135,4 @@ abstract class AnimexxCalSource
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -249,7 +249,7 @@ class AnimexxCalSourcePrivate extends AnimexxCalSource
|
||||||
return $obj_id . ".ics";
|
return $obj_id . ".ics";
|
||||||
}
|
}
|
||||||
|
|
||||||
private function jqcal2wdcal($row, $usr_id) {
|
private function jqcal2wdcal($row, $usr_id, $base_path) {
|
||||||
$evo = new DBClass_friendica_jqcalendar($row);
|
$evo = new DBClass_friendica_jqcalendar($row);
|
||||||
$not = q("SELECT COUNT(*) num FROM %s%snotifications WHERE `ical_uri` = '%s' AND `ical_recurr_uri` = '%s'",
|
$not = q("SELECT COUNT(*) num FROM %s%snotifications WHERE `ical_uri` = '%s' AND `ical_recurr_uri` = '%s'",
|
||||||
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($row["ical_uri"]), $row["ical_recurr_uri"]
|
CALDAV_SQL_DB, CALDAV_SQL_PREFIX, dbesc($row["ical_uri"]), $row["ical_recurr_uri"]
|
||||||
|
@ -274,8 +274,8 @@ class AnimexxCalSourcePrivate extends AnimexxCalSource
|
||||||
"location" => $evo->Location,
|
"location" => $evo->Location,
|
||||||
"attendees" => '',
|
"attendees" => '',
|
||||||
"has_notification" => ($not[0]["num"] > 0 ? 1 : 0),
|
"has_notification" => ($not[0]["num"] > 0 ? 1 : 0),
|
||||||
"url_detail" => "/dav/wdcal/" . $evo->ical_uri . "/",
|
"url_detail" => $base_path . $evo->ical_uri . "/",
|
||||||
"url_edit" => "/dav/wdcal/" . $evo->ical_uri . "/edit/",
|
"url_edit" => $base_path . $evo->ical_uri . "/edit/",
|
||||||
"special_type" => "",
|
"special_type" => "",
|
||||||
);
|
);
|
||||||
return $arr;
|
return $arr;
|
||||||
|
@ -284,9 +284,10 @@ class AnimexxCalSourcePrivate extends AnimexxCalSource
|
||||||
/**
|
/**
|
||||||
* @param string $sd
|
* @param string $sd
|
||||||
* @param string $ed
|
* @param string $ed
|
||||||
|
* @param string $base_path
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function listItemsByRange($sd, $ed)
|
public function listItemsByRange($sd, $ed, $base_path)
|
||||||
{
|
{
|
||||||
|
|
||||||
$usr_id = IntVal($this->calendarDb->uid);
|
$usr_id = IntVal($this->calendarDb->uid);
|
||||||
|
@ -300,7 +301,7 @@ class AnimexxCalSourcePrivate extends AnimexxCalSource
|
||||||
$usr_id, $this->getNamespace(), $this->namespace_id, dbesc($von), dbesc($bis));
|
$usr_id, $this->getNamespace(), $this->namespace_id, dbesc($von), dbesc($bis));
|
||||||
|
|
||||||
$events = array();
|
$events = array();
|
||||||
foreach ($evs as $row) $events[] = $this->jqcal2wdcal($row, $usr_id);
|
foreach ($evs as $row) $events[] = $this->jqcal2wdcal($row, $usr_id, $base_path);
|
||||||
|
|
||||||
return $events;
|
return $events;
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ function wdcal_printCalendar($calendars, $calendar_preselected, $data_feed_url,
|
||||||
$x .= '<label style="margin-left: 10px; margin-right: 10px;"><input type="checkbox" name="cals[]" value="' . $cal["ns"] . '-' . $cal["id"] . '"';
|
$x .= '<label style="margin-left: 10px; margin-right: 10px;"><input type="checkbox" name="cals[]" value="' . $cal["ns"] . '-' . $cal["id"] . '"';
|
||||||
$found = false;
|
$found = false;
|
||||||
foreach ($calendar_preselected as $pre) if ($pre["ns"] == $cal["ns"] && $pre["id"] == $cal["id"]) $found = true;
|
foreach ($calendar_preselected as $pre) if ($pre["ns"] == $cal["ns"] && $pre["id"] == $cal["id"]) $found = true;
|
||||||
if ($found) $x .= 'checked';
|
if ($found) $x .= ' checked';
|
||||||
$x .= '> ' . escape_tags($cal["displayname"]) . '</label> ';
|
$x .= '> ' . escape_tags($cal["displayname"]) . '</label> ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ function wdcal_printCalendar($calendars, $calendar_preselected, $data_feed_url,
|
||||||
|
|
||||||
$x .= '<div class="ctoolbar">
|
$x .= '<div class="ctoolbar">
|
||||||
<div class="fbutton faddbtn" style="float: right;">
|
<div class="fbutton faddbtn" style="float: right;">
|
||||||
<div><a href="/dav/settings/"><span>' . t("Settings") . ' / ' . t("Help") . '</span></a></div>
|
<div><a href="' . $a->get_baseurl() . '/dav/settings/"><span>' . t("Settings") . ' / ' . t("Help") . '</span></a></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="btnseparator"></div>
|
<div class="btnseparator"></div>
|
||||||
<div class="fbutton showtodaybtn">
|
<div class="fbutton showtodaybtn">
|
||||||
|
@ -191,7 +191,7 @@ function wdcal_getDetailPage($uri, $recurr_uri)
|
||||||
$details = $cs->getItemByUri($uri);
|
$details = $cs->getItemByUri($uri);
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
notification(t("Error") . ": " . $e);
|
notification(t("Error") . ": " . $e);
|
||||||
goaway("/dav/wdcal/");
|
goaway($a->get_baseurl() . "/dav/wdcal/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ function wdcal_postEditPage($uri, $recurr_uri)
|
||||||
$a = get_app();
|
$a = get_app();
|
||||||
$localization = wdcal_local::getInstanceByUser($a->user["uid"]);
|
$localization = wdcal_local::getInstanceByUser($a->user["uid"]);
|
||||||
|
|
||||||
check_form_security_token_redirectOnErr("/dav/wdcal/", "caledit");
|
check_form_security_token_redirectOnErr($a->get_baseurl() . "/dav/wdcal/", "caledit");
|
||||||
|
|
||||||
if (isset($_REQUEST["allday"])) {
|
if (isset($_REQUEST["allday"])) {
|
||||||
$start = $localization->date_parseLocal($_REQUEST["start_date"] . " 00:00");
|
$start = $localization->date_parseLocal($_REQUEST["start_date"] . " 00:00");
|
||||||
|
@ -236,7 +236,7 @@ function wdcal_postEditPage($uri, $recurr_uri)
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
notification(t("Error") . ": " . $e);
|
notification(t("Error") . ": " . $e);
|
||||||
}
|
}
|
||||||
goaway("/dav/wdcal/");
|
goaway($a->get_baseurl() . "/dav/wdcal/");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -323,8 +323,8 @@ function wdcal_getEditPage($uri, $recurr_uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$out = "<a href='/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
|
$out = "<a href='" . $a->get_baseurl() . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
|
||||||
$out .= "<form method='POST' action='/dav/wdcal/$uri/edit/'><input type='hidden' name='form_security_token' value='" . get_form_security_token('caledit') . "'>\n";
|
$out .= "<form method='POST' action='" . $a->get_baseurl() . "/dav/wdcal/$uri/edit/'><input type='hidden' name='form_security_token' value='" . get_form_security_token('caledit') . "'>\n";
|
||||||
|
|
||||||
$out .= "<label for='cal_subject'>Subject:</label>
|
$out .= "<label for='cal_subject'>Subject:</label>
|
||||||
<input name='color' id='cal_color' value='" . (strlen($event["Color"]) != 7 ? "#5858ff" : escape_tags($event["Color"])) . "'>
|
<input name='color' id='cal_color' value='" . (strlen($event["Color"]) != 7 ? "#5858ff" : escape_tags($event["Color"])) . "'>
|
||||||
|
@ -389,19 +389,19 @@ function wdcal_getSettingsPage(&$a)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($_REQUEST["save"])) {
|
if (isset($_REQUEST["save"])) {
|
||||||
check_form_security_token_redirectOnErr('/dav/settings/', 'calprop');
|
check_form_security_token_redirectOnErr($a->get_baseurl() . '/dav/settings/', 'calprop');
|
||||||
set_pconfig($a->user["uid"], "dav", "dateformat", $_REQUEST["wdcal_date_format"]);
|
set_pconfig($a->user["uid"], "dav", "dateformat", $_REQUEST["wdcal_date_format"]);
|
||||||
info(t('The new values have been saved.'));
|
info(t('The new values have been saved.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$o = "";
|
$o = "";
|
||||||
|
|
||||||
$o .= "<a href='/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
|
$o .= "<a href='" . $a->get_baseurl() . "/dav/wdcal/'>" . t("Go back to the calendar") . "</a><br><br>";
|
||||||
|
|
||||||
$o .= '<h3>' . t('Calendar Settings') . '</h3>';
|
$o .= '<h3>' . t('Calendar Settings') . '</h3>';
|
||||||
|
|
||||||
$current_format = wdcal_local::getInstanceByUser($a->user["uid"]);
|
$current_format = wdcal_local::getInstanceByUser($a->user["uid"]);
|
||||||
$o .= '<form method="POST" action="/dav/settings/">';
|
$o .= '<form method="POST" action="' . $a->get_baseurl() . '/dav/settings/">';
|
||||||
$o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('calprop') . "'>\n";
|
$o .= "<input type='hidden' name='form_security_token' value='" . get_form_security_token('calprop') . "'>\n";
|
||||||
|
|
||||||
$o .= '<label for="wdcal_date_format">' . t('Date format') . ':</label><select name="wdcal_date_format" id="wdcal_date_format" size="1">';
|
$o .= '<label for="wdcal_date_format">' . t('Date format') . ':</label><select name="wdcal_date_format" id="wdcal_date_format" size="1">';
|
||||||
|
@ -441,7 +441,7 @@ function wdcal_getSettingsPage(&$a)
|
||||||
<li>Add a new account</li>
|
<li>Add a new account</li>
|
||||||
<li>Other...</li>
|
<li>Other...</li>
|
||||||
<li>Calendar -> CalDAV-Account</li>
|
<li>Calendar -> CalDAV-Account</li>
|
||||||
<li><b>Server:</b> " . $a->get_hostname() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
|
<li><b>Server:</b> " . $a->get_baseurl() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
|
||||||
</ul>";
|
</ul>";
|
||||||
|
|
||||||
$o .= '<h4>' . t('Synchronizing your Friendica-Contacts with the iPhone') . '</h4>';
|
$o .= '<h4>' . t('Synchronizing your Friendica-Contacts with the iPhone') . '</h4>';
|
||||||
|
@ -452,7 +452,7 @@ function wdcal_getSettingsPage(&$a)
|
||||||
<li>Add a new account</li>
|
<li>Add a new account</li>
|
||||||
<li>Other...</li>
|
<li>Other...</li>
|
||||||
<li>Contacts -> CardDAV-Account</li>
|
<li>Contacts -> CardDAV-Account</li>
|
||||||
<li><b>Server:</b> " . $a->get_hostname() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
|
<li><b>Server:</b> " . $a->get_baseurl() . "/dav/ / <b>Username/Password:</b> <em>the same as your friendica-login</em></li>
|
||||||
</ul>";
|
</ul>";
|
||||||
|
|
||||||
return $o;
|
return $o;
|
||||||
|
|
14
dav/main.php
14
dav/main.php
|
@ -29,9 +29,6 @@ function dav_module()
|
||||||
function dav_init(&$a)
|
function dav_init(&$a)
|
||||||
{
|
{
|
||||||
|
|
||||||
error_reporting(E_ALL);
|
|
||||||
ini_set("display_errors", 1);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Recommended settings:
|
* Recommended settings:
|
||||||
* ALTER TABLE `photo` ADD INDEX ( `contact-id` )
|
* ALTER TABLE `photo` ADD INDEX ( `contact-id` )
|
||||||
|
@ -91,7 +88,7 @@ function dav_init(&$a)
|
||||||
if ($a->argc >= 2 && $a->argv[1] == "wdcal") {
|
if ($a->argc >= 2 && $a->argv[1] == "wdcal") {
|
||||||
|
|
||||||
if ($a->argc >= 3 && $a->argv[2] == "feed") {
|
if ($a->argc >= 3 && $a->argv[2] == "feed") {
|
||||||
wdcal_print_feed();
|
wdcal_print_feed($a->get_baseurl() . "/dav/wdcal/");
|
||||||
killme();
|
killme();
|
||||||
} elseif ($a->argc >= 3 && strlen($a->argv[2]) > 0) {
|
} elseif ($a->argc >= 3 && strlen($a->argv[2]) > 0) {
|
||||||
wdcal_addRequiredHeadersEdit();
|
wdcal_addRequiredHeadersEdit();
|
||||||
|
@ -133,7 +130,8 @@ function dav_init(&$a)
|
||||||
// The object tree needs in turn to be passed to the server class
|
// The object tree needs in turn to be passed to the server class
|
||||||
$server = new Sabre_DAV_Server($tree);
|
$server = new Sabre_DAV_Server($tree);
|
||||||
|
|
||||||
$server->setBaseUri("/" . CALDAV_URL_PREFIX);
|
$url = parse_url($a->get_baseurl());
|
||||||
|
$server->setBaseUri(CALDAV_URL_PREFIX);
|
||||||
|
|
||||||
$authPlugin = new Sabre_DAV_Auth_Plugin($authBackend, 'SabreDAV');
|
$authPlugin = new Sabre_DAV_Auth_Plugin($authBackend, 'SabreDAV');
|
||||||
$server->addPlugin($authPlugin);
|
$server->addPlugin($authPlugin);
|
||||||
|
@ -186,7 +184,7 @@ function dav_content()
|
||||||
$cals = dav_getMyCals($a->user["uid"]);
|
$cals = dav_getMyCals($a->user["uid"]);
|
||||||
$cals_show = array();
|
$cals_show = array();
|
||||||
foreach ($cals as $e) $cals_show[] = array("ns" => $e->namespace, "id" => $e->namespace_id, "displayname" => $e->displayname);
|
foreach ($cals as $e) $cals_show[] = array("ns" => $e->namespace, "id" => $e->namespace_id, "displayname" => $e->displayname);
|
||||||
$x = wdcal_printCalendar($cals, $cals_show, "/dav/wdcal/feed/", "week", 0, 200);
|
$x = wdcal_printCalendar($cals, $cals_show, $a->get_baseurl() . "/dav/wdcal/feed/", "week", 0, 200);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $x;
|
return $x;
|
||||||
|
@ -223,7 +221,7 @@ function dav_profile_tabs_hook(&$a, &$b)
|
||||||
{
|
{
|
||||||
$b["tabs"][] = array(
|
$b["tabs"][] = array(
|
||||||
"label" => t('Calendar'),
|
"label" => t('Calendar'),
|
||||||
"url" => "/dav/wdcal/",
|
"url" => $a->get_baseurl() . "/dav/wdcal/",
|
||||||
"sel" => "",
|
"sel" => "",
|
||||||
"title" => t('Extended calendar with CalDAV-support'),
|
"title" => t('Extended calendar with CalDAV-support'),
|
||||||
);
|
);
|
||||||
|
@ -281,4 +279,4 @@ function dav_plugin_admin(&$a, &$o)
|
||||||
$tables = dav_get_create_statements();
|
$tables = dav_get_create_statements();
|
||||||
foreach ($tables as $t) $o .= escape_tags($t . "\n\n");
|
foreach ($tables as $t) $o .= escape_tags($t . "\n\n");
|
||||||
$o .= "</pre></blockquote>";
|
$o .= "</pre></blockquote>";
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,8 +515,10 @@ border-bottom:2px solid #c3c3ff;
|
||||||
position: absolute; visibility: hidden; font-size: 9pt; top: 0px; left: 0px
|
position: absolute; visibility: hidden; font-size: 9pt; top: 0px; left: 0px
|
||||||
}
|
}
|
||||||
.bubble-table {
|
.bubble-table {
|
||||||
width: 100%; TABLE-LAYOUT: fixed
|
width: 100%; TABLE-LAYOUT: fixed;
|
||||||
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
.bubble-table > tbody > tr > td { padding: 0; }
|
||||||
.bubble-cell-side {
|
.bubble-cell-side {
|
||||||
width: 25px
|
width: 25px
|
||||||
}
|
}
|
||||||
|
@ -685,4 +687,4 @@ border-bottom:2px solid #c3c3ff;
|
||||||
.monthdayshow:hover
|
.monthdayshow:hover
|
||||||
{
|
{
|
||||||
text-decoration:underline;
|
text-decoration:underline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@ class FriendicaCalSourceEvents extends AnimexxCalSource
|
||||||
$end = wdcal_mySql2PhpTime($row["data_end"]);
|
$end = wdcal_mySql2PhpTime($row["data_end"]);
|
||||||
if ($row["data_allday"]) $end--;
|
if ($row["data_allday"]) $end--;
|
||||||
$start = wdcal_mySql2PhpTime($row["data_start"]);
|
$start = wdcal_mySql2PhpTime($row["data_start"]);
|
||||||
|
$a = get_app();
|
||||||
$arr = array(
|
$arr = array(
|
||||||
"uri" => $row["data_uri"],
|
"uri" => $row["data_uri"],
|
||||||
"subject" => escape_tags($row["data_subject"]),
|
"subject" => escape_tags($row["data_subject"]),
|
||||||
|
@ -99,7 +100,7 @@ class FriendicaCalSourceEvents extends AnimexxCalSource
|
||||||
"location" => $row["data_location"],
|
"location" => $row["data_location"],
|
||||||
"attendees" => '',
|
"attendees" => '',
|
||||||
"has_notification" => false,
|
"has_notification" => false,
|
||||||
"url_detail" => "/dav/wdcal/" . $row["data_uri"] . "/",
|
"url_detail" => $a->get_baseurl() . "/dav/wdcal/" . $row["data_uri"] . "/",
|
||||||
"url_edit" => "",
|
"url_edit" => "",
|
||||||
"special_type" => ($row["data_type"] == "birthday" ? "birthday" : ""),
|
"special_type" => ($row["data_type"] == "birthday" ? "birthday" : ""),
|
||||||
);
|
);
|
||||||
|
@ -109,9 +110,10 @@ class FriendicaCalSourceEvents extends AnimexxCalSource
|
||||||
/**
|
/**
|
||||||
* @param string $sd
|
* @param string $sd
|
||||||
* @param string $ed
|
* @param string $ed
|
||||||
|
* @param string $base_path
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function listItemsByRange($sd, $ed)
|
public function listItemsByRange($sd, $ed, $base_path)
|
||||||
{
|
{
|
||||||
$usr_id = IntVal($this->calendarDb->uid);
|
$usr_id = IntVal($this->calendarDb->uid);
|
||||||
|
|
||||||
|
@ -149,8 +151,9 @@ class FriendicaCalSourceEvents extends AnimexxCalSource
|
||||||
public function getItemDetailRedirect($uri) {
|
public function getItemDetailRedirect($uri) {
|
||||||
$x = explode("@", $uri);
|
$x = explode("@", $uri);
|
||||||
$y = explode("-", $x[0]);
|
$y = explode("-", $x[0]);
|
||||||
|
$a = get_app();
|
||||||
if (count($y) != 3) {
|
if (count($y) != 3) {
|
||||||
goaway("/dav/wdcal/");
|
goaway($a->get_baseurl() . "/dav/wdcal/");
|
||||||
killme();
|
killme();
|
||||||
}
|
}
|
||||||
$a = get_app();
|
$a = get_app();
|
||||||
|
|
Loading…
Reference in a new issue