Skip to content
Snippets Groups Projects
Select Git revision
  • 3d8cb20aef2c55cadd38dccc3f51128d7e357ecf
  • main default protected
  • step-3263
  • feature/plugins-cli
  • feature/vite
  • step-2484-peerreview
  • biest/issue-5051
  • tests/simplify-jsonapi-tests
  • fix/typo-in-1a70031
  • feature/broadcasting
  • database-seeders-and-factories
  • feature/peer-review-2
  • feature-feedback-jsonapi
  • feature/peerreview
  • feature/balloon-plus
  • feature/stock-images-unsplash
  • tic-2588
  • 5.0
  • 5.2
  • biest/unlock-blocks
  • biest-1514
21 results

TaskFeedbackDelete.php

Blame
  • Forked from Stud.IP / Stud.IP
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    visual.inc.php 17.90 KiB
    <?php
    # Lifter002: TODO
    # Lifter007: TODO
    # Lifter003: TODO
    # Lifter010: TODO
    
    
    // Wrapper for formatted content (defined as a constant since it is used
    // in the unit test defined in tests/unit/lib/VisualTest.php as well).
    define('FORMATTED_CONTENT_WRAPPER', '<div class="formatted-content ck-content">%s</div>');
    
    //// Functions for processing marked-up text (Stud.IP markup, HTML, JS).
    
    use Studip\Markup;
    
    function htmlReady($what, $trim=TRUE, $br=FALSE, $double_encode=true) {
        return Markup::htmlReady($what, $trim, $br, $double_encode);
    }
    
    /**
     * Prepare text for wysiwyg (if enabled), otherwise convert special
     * characters using htmlReady.
     *
     * @param  string  $text  The text.
     * @param  boolean $trim  Trim text before applying markup rules, if TRUE.
     * @param  boolean $br    Replace newlines by <br>, if TRUE and wysiwyg editor disabled.
     * @param  boolean $double_encode  Encode existing HTML entities, if TRUE and wysiwyg editor disabled.
     * @return string         The converted string.
     */
    function wysiwygReady($what, $trim=TRUE, $br=FALSE, $double_encode=true) {
        return Markup::wysiwygReady($what, $trim, $br, $double_encode);
    }
    
    function jsReady ($what, $target = 'script-single') {
        switch ($target) {
    
        case "script-single" :
            return addcslashes($what, "\\'\n\r");
        break;
    
        case "script-double" :
            return addcslashes($what, "\\\"\n\r");
        break;
    
        case "inline-single" :
            return htmlReady(addcslashes($what, "\\'\n\r"), false, false, true);
        break;
    
        case "inline-double" :
            return htmlReady(addcslashes($what, "\\\"\n\r"), false, false, true);
        break;
    
        }
        return addslashes($what);
    }
    
    /**
     * Quote a piece of text, optionally include the author's name.
     *
     * @param string $text Text that is to be quoted.
     * @param string $author Name of the text's author (optional).
     *
     * @return string The quoted text.
     */
    function quotes_encode($text, $author = '')
    {
        // If quoting is changed update these functions:
        // - StudipFormat::markupQuote
        //   lib/classes/StudipFormat.php
        // - quotes_encode lib/visual.inc.php
        // - STUDIP.Forum.citeEntry > quote
        //   public/plugins_packages/core/Forum/javascript/forum.js
        // - studipQuotePlugin > insertStudipQuote
        //   public/assets/javascripts/ckeditor/plugins/studip-quote/plugin.js
    
        $text = Markup::markupToHtml($text);
    
        if ($author) {
            $title = sprintf(_('%s hat geschrieben:'), htmlReady($author));
            $text = '<div class="author">' . $title . '</div>' . $text;
        }
        $text = sprintf('<blockquote>%s</blockquote><p>&nbsp;</p>', $text);
        return Markup::markAsHtml($text);
    }
    
    /**
     * Common function to get all special Stud.IP formattings.
     *
     * @access public
     * @param string  $text  Marked-up text.
     * @param boolean $trim  Trim leading and trailing whitespace, if TRUE.
     * @return string        HTML code computed by applying markup-rules.
     */
    function formatReady($text, $trim = true)
    {
        $formatted = Markup::apply(new StudipFormat(), $text, $trim);
    
        return $formatted !== '' ? sprintf(FORMATTED_CONTENT_WRAPPER, $formatted) : '';
    }
    
    /**
     * Simplified version of formatReady that handles link formatting only.
     *
     * @param  string $text   Marked-up text.
     * @param  bool   $nl2br  Convert newlines to <br>.
     * @return string         Marked-up text with markup-links converted to
     *                        HTML-links.
     */
    function formatLinks($text, $nl2br = true) {
        $link_markup_rule = StudipCoreFormat::getStudipMarkup('links');
        $email_markup_rule = StudipCoreFormat::getStudipMarkup('emails');
        $markup = new TextFormat();
        $markup->addMarkup(
            'links',
            $link_markup_rule['start'],
            $link_markup_rule['end'] ?? '',
            $link_markup_rule['callback']
        );
        $markup->addMarkup(
            'emails',
            $email_markup_rule['start'],
            $email_markup_rule['end'] ?? '',
            $email_markup_rule['callback']
        );
        return $markup->format(htmlReady($text, true, $nl2br));
    }
    
    /**
     * Special version of formatReady for wiki-webs.
     *
     * @access public
     * @param  string $what  Marked-up text.
     * @param  string $trim  Trim leading and trailing whitespace, if TRUE.
     * @param  string $range_id the id of the course or institute
     * @param  string $page_id the id of the page
     * @return string        HTML code computed by applying markup-rules.
     */
    function wikiReady($text, $trim=TRUE, $range_id = null, $page_id = null) {
        $formatted = Markup::apply(new WikiFormat($range_id, $page_id), $text, $trim);
    
        return $formatted !== '' ? sprintf(FORMATTED_CONTENT_WRAPPER, $formatted) : '';
    }
    
    /**
     * Special version of formatReady for blubber, which includes hashtags
     *
     * @access public
     * @param  string $what  Marked-up text.
     * @param  string $trim  Trim leading and trailing whitespace, if TRUE.
     * @return string        HTML code computed by applying markup-rules.
     */
    function blubberReady($text, $trim=TRUE) {
        $formatted = Markup::apply(new BlubberFormat(), $text, $trim);
    
        return $formatted !== '' ? sprintf(FORMATTED_CONTENT_WRAPPER, $formatted) : '';
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    /**
    * decodes html entities to normal characters
    *
    * @access   public
    * @param    string
    * @return   string
    */
    function decodeHTML ($string) {
        return html_entity_decode($string, ENT_QUOTES);
    }
    
    /**
    * formats a ~~~~ wiki signature with username and timestamp
    * @param string
    * @param unix timestamp
    */
    function preg_call_format_signature($username, $timestamp) {
        $fullname = get_fullname_from_uname($username);
        $date = strftime('%x, %X', $timestamp);
        return '<span style="font-size: 75%">-- <a href="'.URLHelper::getLink('dispatch.php/profile', ['username' => $username]).'">'.htmlReady($fullname).'</a> '.htmlReady($date).'</span>';
    }
    
    
    /**
    * removes all characters used by quick-format-syntax
    *
    * @access   public
    * @param    string
    * @return   string
    */
    function kill_format ($text) {
        if (Markup::isHtml($text)) {
            $is_fallback = Markup::isHtmlFallback($text);
            $text = Markup::removeHtml($text);
    
            if (!$is_fallback) {
                // pure HTML - no Stud.IP markup to remove
                return $text;
            }
        }
    
        // remove Stud.IP markup
        $text = preg_replace("'\n?\r\n?'", "\n", $text);
        // wir wandeln [code] einfach in [pre][nop] um und sind ein Problem los ... :-)
        $text = preg_replace_callback("|(\[/?code\])|isU", function ($a) {
            return $a[0] === '[code]' ? '[pre][nop]' : '[/nop][/pre]';
        }, $text);
    
        $pattern = [
                        "'(^|\n)\!{1,4}(.+)$'m",      // Ueberschriften
                        "'(\n|\A)(-|=)+ (.+)$'m",     // Aufzaehlungslisten
                        "'%%(\S|\S.*?\S)%%'s",        // ML-kursiv
                        "'\*\*(\S|\S.*?\S)\*\*'s",    // ML-fett
                        "'__(\S|\S.*?\S)__'s",        // ML-unterstrichen
                        "'##(\S|\S.*?\S)##'s",        // ML-diktengleich
                        "'\+\+(((\+\+)*)(\S|\S.*?\S)?\\2)\+\+'s",  // ML-groesser
                        "'--(((--)*)(\S|\S.*?\S)?\\2)--'s",        // ML-kleiner
                        "'>>(\S|\S.*?\S)>>'is",  // ML-hochgestellt
                        "'<<(\S|\S.*?\S)<<'is",  // ML-tiefgestellt
                        "'{-(.+?)-}'is" ,        // durchgestrichen
                        "'\n\n  (((\n\n)  )*(.+?))(\Z|\n\n(?! ))'s",  // Absatz eingerueckt
                        "'(?<=\n|^)--+(\d?)(\n|$|(?=<))'m", // Trennlinie
                        "'\[pre\](.+?)\[/pre\]'is" ,        // praeformatierter Text
                        "'\[nop\].+\[/nop\]'isU",
                        //"'\[.+?\](((http\://|https\://|ftp\://)?([^/\s]+)(.[^/\s]+){2,})|([-a-z0-9_]+(\.[_a-z0-9-]+)*@([a-z0-9-]+(\.[a-z0-9-]+)+)))'i",
                        "'\[(.+?)\](((http\://|https\://|ftp\://)?([^/\s]+)(\.[^/\s]+){2,}(/[^\s]*)?)|([-a-z0-9_]+(\.[_a-z0-9-]+)*@([a-z0-9-]+(\.[a-z0-9-]+)+)))'i",
                //      "'\[quote=.+?quote\]'is",    // quoting
    
                        ];
        $replace = [
                        "\\1\\2", "\\1\\3",
                        "\\1", "\\1", "\\1", "\\1", "\\1", "\\1",
                        "\\1", "\\1", "\\1", "\n\\1\n", "", "\\1",'[nop] [/nop]',
                        //"\\2",
                        '$1 ($2)',
                         //"",
                          '$1$2'];
        $callback = function ($c) {
            return function ($m) use ($c) {
                return $m[1] . mb_substr(str_replace($c, ' ', $m[2]), 0, -1);
            };
        };
        $pattern_callback = [
            "'(^|\s)%(?!%)(\S+%)+'" => $callback('%'),     // SL-kursiv
            "'(^|\s)\*(?!\*)(\S+\*)+'" => $callback('*') ,  // SL-fett
            "'(^|\s)_(?!_)(\S+_)+'" => $callback('_'),     // SL-unterstrichen
            "'(^|\s)#(?!#)(\S+#)+'" => $callback('#'),     // SL-diktengleich
            "'(^|\s)\+(?!\+)(\S+\+)+'" => $callback('+'),  // SL-groesser
            "'(^|\s)-(?!-)(\S+-)+'" => $callback('-'),     // SL-kleiner
            "'(^|\s)>(?!>)(\S+>)+'" => $callback('>'),     // SL-hochgestellt
            "'(^|\s)<(?!<)(\S+<)+'" => $callback('<'),     // SL-tiefgestellt);
        ];
    
        if (preg_match_all("'\[nop\](.+)\[/nop\]'isU", $text, $matches)) {
            $text = preg_replace($pattern, $replace, $text);
            $text = preg_replace_callback_array($pattern_callback, $text);
            $text = explode("[nop] [/nop]", $text);
            $i = 0;
            $all = '';
            foreach ($text as $w) {
                $all .= $w . ($matches[1][$i++] ?? '');
            }
    
            return $all;
        }
        $text = preg_replace($pattern, $replace, $text);
        $text = preg_replace_callback_array($pattern_callback, $text);
        return $text;
    }
    
    function isURL($url) {
        return filter_var($url, FILTER_VALIDATE_URL) !== false;
    }
    
    function isLinkIntern($url) {
        $pum = @parse_url(TransformInternalLinks($url));
    
        if (!$pum) {
            return false;
        }
    
        // If given $url is pointing to an anchor, it should be internal
        if (count($pum) === 1 && isset($pum['fragment'])) {
            return true;
        }
    
        return in_array($pum['scheme'] ?? null, ['https', 'http', null], true)
            && in_array($pum['host'] ?? null, [$_SERVER['SERVER_NAME'] ?? null, null], true)
            && in_array($pum['port'] ?? null, [$_SERVER['SERVER_PORT'] ?? null, null], true)
            && mb_strpos($pum['path'] ?? '', $GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']) === 0;
    }
    
    /**
     * convert links with 'umlauten' to punycode
     *
     * @param string $link link to convert
     * @return string  link in punycode
     *
     * @throws \Algo26\IdnaConvert\Exception\AlreadyPunycodeException
     * @throws \Algo26\IdnaConvert\Exception\InvalidCharacterException
     */
    function idna_link(string $link) {
        if (!Config::get()->CONVERT_IDNA_URL) {
            return $link;
        }
    
        $pu = parse_url($link);
        if (
            isset($pu['host'])
            && preg_match('/&\w+;/i', $pu['host']) //umlaute?  (html-coded)
            && preg_match('#^([^/]*)//([^/?]*)([/?].*)?$#i',$link, $matches)
        ) {
            $IDN = new Algo26\IdnaConvert\ToIdn();
            $out = $IDN->convert(decodeHTML($matches[2])); // false by error
            if ($out) {
                return $matches[1] . '//' . htmlReady($out) . ($matches[3] ?? '');
            }
        }
        return $link;
    }
    
    /**
     * create symbols from the shorts
     *
     * This functions converts the short, locatet in the config.inc
     * into the assigned pictures. A tooltip which shows the symbol
     * code is given, too.
     *
     * @access   public
     *
     * @param        string  the text to convert
     *
     * @return       string  convertet text
    */
    function symbol ($text = '')
    {
        if (!$text) {
            return $text;
        }
    
        $patterns = [];
        $replaces = [];
        //symbols in short notation
        foreach ($GLOBALS['SYMBOL_SHORT'] as $key => $value) {
            $patterns[] = "'" . preg_quote($key) . "'m";
            $replaces[] = $value;
        }
    
        return preg_replace($patterns, $replaces, $text);
    }
    
    //Beschneidungsfunktion fuer alle printhead Ausgaben
    function mila ($titel, $size = 60) {
        global $auth;
    
        if (!empty($auth->auth['jscript']) && $size == 60) {
            //hier wird die maximale Laenge berechnet, nach der Abgeschnitten wird (JS dynamisch)
            if (mb_strlen($titel) > $auth->auth['xres'] / 13) {
                $titel = mb_substr($titel, 0, $auth->auth['xres'] / 13) . '... ';
            }
        } elseif (mb_strlen ($titel) >$size) {
            $titel = mb_substr($titel, 0, $size) . '... ';
        }
        return $titel;
    }
    
    /**
     * Returns a given text as html tooltip
     *
     * title and alt attribute is default, with_popup means a JS alert box
     * activated on click
     *
     * @param        string  $text
     * @param        boolean $with_alt    return text with alt attribute
     * @param        boolean $with_popup  return text with JS alert box on click
     * @return       string
     */
    function tooltip ($text, $with_alt = TRUE, $with_popup = FALSE) {
        return arrayToHtmlAttributes(tooltip2($text, $with_alt, $with_popup));
    }
    
    /**
     * Returns a given text as an array of html attributes used as tooltip
     *
     * title and alt attribute is default, with_popup means a JS alert box
     * activated on click
     *
     * @param        string  $text
     * @param        boolean $with_alt    return text with alt attribute
     * @param        boolean $with_popup  return text with JS alert box on click
     * @return       string
     */
    function tooltip2($text, $with_alt = TRUE, $with_popup = FALSE) {
    
        $ret = [];
    
        if ($with_popup) {
            $ret['onClick'] = "alert('".JSReady($text, "alert")."');";
        }
    
        $text = preg_replace("/(\n\r|\r\n|\n|\r)/", " ", $text);
        $text = htmlReady($text);
    
        if ($with_alt) {
            $ret['alt'] = $text;
        }
        $ret['title'] = $text;
        $ret['tabindex'] = '0';
    
        return $ret;
    }
    
    /**
     * returns a html-snippet with an icon and a tooltip on it
     *
     * @param string|null $text      tooltip text, html gets encoded
     * @param bool        $important render icon in "important" style
     * @param bool        $html      tooltip text is HTML content
     * @param bool        $alt_info
     * @return string
     */
    function tooltipIcon(?string $text, bool $important = false, bool $html = false, bool $alt_info= false): string
    {
        if (!trim($text)) {
            return '';
        }
    
        // render tooltip
        $template = $GLOBALS['template_factory']->open('shared/tooltip');
        return $template->render(compact('text', 'important', 'html', 'alt_info'));
    }
    
    /**
     * returns a html-snippet with an icon and a tooltip on it
     *
     * @param string|null $text      tooltip text, html is rendered as is
     * @param bool        $important render icon in "important" style
     * @return string
     */
    function tooltipHtmlIcon(?string $text, bool $important = false)
    {
        return tooltipIcon($text, $important, true);
    }
    
    /**
     * detects internal links in a given string and convert used domain to the domain
     * actually used (only necessary if more than one domain exists), relative URLs are
     * converted to absolute URLs
     *
     * @param    string  $str URL/Link to convert
     * @return   string  converted URL/Link
    */
    function TransformInternalLinks($str){
        $str = trim($str);
    
        if (!$str) {
            return '';
        }
    
        if (mb_strpos($str, 'http') !== 0) {
            if ($str[0] === '#' || preg_match('/^[a-z][a-z0-9+.-]*:/i', $str)) {
                return $str;
            }
            if ($str[0] === '/') {
                $str = mb_substr($str, mb_strlen($GLOBALS['CANONICAL_RELATIVE_PATH_STUDIP']));
            }
            $str = $GLOBALS['ABSOLUTE_URI_STUDIP'] . $str;
        }
        if (!empty($GLOBALS['STUDIP_DOMAINS']) && count($GLOBALS['STUDIP_DOMAINS']) > 1) {
            if (!isset($GLOBALS['TransformInternalLinks_domainData'])){
                $domain_data['domains'] = '';
                foreach ($GLOBALS['STUDIP_DOMAINS'] as $studip_domain) $domain_data['domains'] .= '|' . preg_quote($studip_domain);
                $domain_data['domains'] = preg_replace("'\|[^/|]*'", '$0[^/]*?', $domain_data['domains']);
                $domain_data['domains'] = mb_substr($domain_data['domains'], 1);
                $domain_data['user_domain'] = preg_replace("'^({$domain_data['domains']})(.*)$'i", "\\1", $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
                $domain_data['user_domain_scheme'] = 'http' . ((!empty($_SERVER['HTTPS']) || $_SERVER['SERVER_PORT'] == 443) ? 's' : '') . '://';
                $GLOBALS['TransformInternalLinks_domainData'] = $domain_data;
            }
            $domain_data = $GLOBALS['TransformInternalLinks_domainData'];
            return preg_replace("'https?\://({$domain_data['domains']})((/[^<\s]*[^\.\s<])*)'i", "{$domain_data['user_domain_scheme']}{$domain_data['user_domain']}\\2", $str);
        } else {
            return $str;
        }
    }
    
    /**
     * Displays the provided exception in a more readable fashion.
     *
     * @param Exception $exception The exception to be displayed
     * @param bool $as_html Indicates whether the exception shall be displayed as
     *                      plain text or html (optional, defaults to plain text)
     * @param bool $deep    Indicates whether any previous exception should be
     *                      included in the output (optional, defaults to false)
     * @return String The exception display either as plain text or html
     */
    function display_exception($exception, $as_html = false, $deep = false) {
        $result  = '';
        $result .= sprintf("%s: %s\n", _('Typ'), get_class($exception));
        $result .= sprintf("%s: %s\n", _('Nachricht'), $exception->getMessage());
        $result .= sprintf("%s: %d\n", _('Code'), $exception->getCode());
    
        $trace = sprintf("  #$ %s(%u)\n", $exception->getFile(), $exception->getLine())
               . '  '  . str_replace("\n", "\n  ", $exception->getTraceAsString());
        $trace = str_replace($GLOBALS['STUDIP_BASE_PATH'] . '/', '', $trace);
        $result .= sprintf("%s:\n%s\n", _('Stack trace'), $trace);
    
        if ($deep && $exception->getPrevious()) {
            $result .= "\n";
            $result .= _('Vorherige Exception:') . "\n";
            $result .= display_exception($exception->getPrevious(), false, $deep);
        }
    
        return $as_html ? nl2br(htmlReady($result)) : $result;
    }
    
    /**
     * Converts an array of attributes to an html attribute string.
     *
     * @param array $attributes Associative array of attributes
     * @return string
     * @since Stud.IP 4.1
     * @todo Nested attribute definitions?
     */
    function arrayToHtmlAttributes(array $attributes) {
        return (string) HTMLAttributes::from($attributes);
    }