Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature-Request :: Medienpool-Dateien schützen #247

Closed
skerbis opened this issue Jan 30, 2017 · 19 comments
Closed

Feature-Request :: Medienpool-Dateien schützen #247

skerbis opened this issue Jan 30, 2017 · 19 comments
Milestone

Comments

@skerbis
Copy link
Contributor

skerbis commented Jan 30, 2017

yform nutzt nicht (mehr) den EP … MEDIA_IS_IN_USE?
Medien können gelöscht werden, obwohl in Verwendung in yform-Tabellen.

@tbaddade tbaddade changed the title yform nutzt nicht mehr den EP … MEDIA_IN_USE? yform nutzt nicht mehr den EP … MEDIA_IS_IN_USE? Jan 30, 2017
@skerbis
Copy link
Contributor Author

skerbis commented Jan 30, 2017

@tbaddade
Copy link
Member

Diese gibt es nicht mehr. mediafile gehört da nicht rein, weil kein Bestandteil vom manager. Das müsste eigentlich direkt in Yform geprüft werden und be_media müsste die jetzigen drei m.E. komplett ersetzen.

@skerbis
Copy link
Contributor Author

skerbis commented Jan 30, 2017

#248

@skerbis
Copy link
Contributor Author

skerbis commented Jan 30, 2017

Hmmm ... die Änderung in meinem PR bringt nichts @dergel
Die Funktion scheint nicht ausgeführt zu werden.

@dergel dergel added this to the Version 2.2 milestone Feb 5, 2017
@christophboecker
Copy link
Contributor

Das lässt sich ja relativ einfach allgmeingültig lösen. rex_yform_field kennt ja die tabellen/felder mit den relevnten Feldtypen. Braucht jemand Code?

@alxndr-w
Copy link
Contributor

alxndr-w commented Sep 9, 2017

@christophboecker gerne her damit :)

@christophboecker
Copy link
Contributor

christophboecker commented Sep 9, 2017

@alexplusde

Hi Alex, ich bin mir aus dem Thread nicht sicher, ob das Feature mal drin war, evtl unabsichtlich rausfiel und in einem Folgerelease wieder reinkommt. Aber egal: hier mein Workaround.

Ich hab die Datei mit der Extension extension_yform.php genannt und nach project/extensions gepackt. In project/lang/de_de.lang stehen zudem zwei Einträge, auf die verwiesen wird:

yform_in_use_article = Artikel (yform)
yform_in_use_media = Medien (yform)

In der project/boot.php steht der Aufruf zur Aktivierung:

include_once( 'extensions/extension_yform.php' );

Und hier die Extension, mit der abgeprüft wird, ob Medien oder Artikel in yform-Feldern der Typen be_media, be_list und be_select_category überprüft werden. Die Liste der Feldtypen kann einfach geändert werden - siehe Kommentare (statisch durch Ändern des Array, dynamisch per Funktion).
Der ganze Krempel ist in einem Objekt gekapselt. Der Kommentar zu is_in_use ist evtl etwas kryptisch geraten, sorry.

<?PHP
/***
    Autor:      Christoph Böcker
    Version:    1.2
    Release:    09.01.2018
*/
 /*-------------------------------------------------------------------------------------------------

 Prüft in YFORM-Tabellen, ob Artikel oder Medien gelöscht werden können

 Die Anforderungen:

    * Allgemeingültige Lösung.
    * Relevante Tabellen und Felder werden automatisch identifiziert z.B. über die Feldtypen
    * Bezgl. benutzereigener Feldtypen (Erweiterung im eigenen Addon) muß die Möglichkeit bestehen,
      den Feldtyp der Suchliste hinzuzufügen.

    Die hier definierte statische Klasse yform_ep stellt hierfür umfassend die Methoden zur Verfügung.
    Sie ist an die Extension-Point
        MEDIA_IS_IN_USE
        PACKAGES_INCLUDED
    gekoppelt. Da sie auf Extension-Points geht, wird sie im Verzeichnis <myaddon>/extensions
    abgelegt und aus der boot.php aktiviert.

        include_once( 'extensions/extension_yform.php' );

    Die Funktion fragt aus der Tabelle rex_yform_fields alle Felder (und Tabellen) ab, die ein
    Feld aufweisen, das vom Typ her Medien- oder Artikel-Daten enthält.

    In jedem Satz der betroffenen Tabellen wird in allen ermittelten Feldern nach dem Objekt
    gesucht. Der Tabellen-Name und die IDs der gefundenen Sätze werden zur Fehlermeldung aufbereitet
    zurückgemeldet.

    Die Liste der relevanten Felder ist vordefiniert ($fieldTypeList) mit den Feldtypen aus yform.
    Über Hilfsfunktionen kann die Liste erweitert werden. Wer private Feldtypen einbringt, die
    auf Medien oder Artikel gehen, kann deren Typ-Kennung damit der Liste hinzufügen

        yform_ep::addFieldtypeMedia( '<fieldtype>' )
        yform_ep::getFieldtypeArticle( '<fieldtype>' )

    Es braucht nur einen .lang-Eintrag

        yform_in_use_article = Artikel "{0} ({1})" kann nicht gelöscht werden (yform)

    Besonders zu erwähnen:

        Es gibt keinen naheliegenden EP wie MEDIA_IS_IN_USE für Artikel bzw. Kategorien.
        Gibt es einfach nicht. Fehlt. War in den Prä-YFORM-Zeiten wohl auch nicht nötig.

        Thomas Blum im Addmon YAKME eine Lösung gebaut auf Basis des EP PACKAGES_INCLUDED.
        Der Trick ist, sich in den früh aufgerufenen EP "PACKAGES_INCLUDED" einzuklinken, und dort

        * abzufangen ob ein API-CALL vorliegt, der Artikel/Kategorie löscht
        * die In-Use-Überprüfung durchzuführen
        * Im Positiv-Fall den API-Call zu verhindern und die Fehlernachricht in den
        Seitenaufbau zu injizieren.

        Das verhindert am Ende, dass der REX_API_CALL zum Löschen von Artikeln (der eben 
        keinen Stopp-Punkt kennt) überhaupt angelaufen wird.
*/

yform_ep::register( );


class yform_ep
{

    /*
        Liste der Feldtypen aus yform, die für Artikel- und Medien-Referenzen vorgesehen sind
    */
    public static $fieldTypeList =
        [
            'media'   => 'be_media',
            'article' => 'be_list,be_link,be_select_category'
        ];


    public static function register()
    {
        rex_extension::register('MEDIA_IS_IN_USE', array('yform_ep','media_is_in_use'), rex_extension::LATE );
        rex_extension::register('PACKAGES_INCLUDED', 'yform_ep::article_is_in_use' );
    }


    public static function media_is_in_use ($objExtensionPoint)
    {
        $warning = $objExtensionPoint->getSubject();
        if ( !isset(self::$fieldTypeList['media']) ) return $warning;
        if ( $result = self::is_in_use( $objExtensionPoint->getParams()['filename'], 'media' ) )
        {
            $warning[] = $result;
        }
        return $warning;

    } // end of media_is_in_use


    static function article_is_in_use( $ep )
    {
        $rexApiCall = rex_request(rex_api_function::REQ_CALL_PARAM, 'string', '');
        if ($rexApiCall == 'category_delete' || $rexApiCall == 'article_delete')
        {

            $id = ($rexApiCall == 'category_delete')
                        ? rex_request('category-id', 'int', 0)
                        : rex_request('article_id', 'int', 0);

            if( $artikel = rex_article::get($id) )
            {
                $result = self::is_in_use( $id, 'article' );
                if( $result )
                {
                    $_REQUEST[rex_api_function::REQ_CALL_PARAM] = '';
                    $result = rex_i18n::msg("yform_in_use_article", $artikel->getName(), $id) . '<br />' . $result;
                    rex_extension::register('PAGE_TITLE_SHOWN', function(rex_extension_point $ep) use ($result) {
                        $ep->setSubject(rex_view::error($result) . $ep->getSubject());
                    });
                } // Ende Fehlermeldung

            } //Ende Artikel-Prüfung

        } // Ende API-Bearbeitung

    } // end of article_is_in_use


    /*------------------------------------------------------------------------------ is_in_use -----

        Ermittle alle Tabellen, in denen der Feldtyp be_media vorkommt. Je Tabelle wird eine Zeile
        zurückgegeben:
            $tabList[..]['yformTable']:   Name der Tabelle
            $tabList[..]['yformName']:    Text für die Ausgabe (aus Tabellen-Name und Titel
            $tabList[..]['yformCol']:     Feldname(n) der Spalten vom Typ be_media
        Beispiel:
            $tabList[..]['yformTable']:   rex_myaddon_recherche
            $tabList[..]['yformName']:    Ergebnisse (rex_myaddon_recherche)
            $tabList[..]['yformCol']:     titelfoto,quellen

        Je Zeile der tabList wird eine SQL-Abfrage auf die Tabelle (yformTable) ausgeführt, die die
        id´s aller Sätze, in denen der Medien-Dateiname, steht zurückliefert.
        Die Inhalte der zu durchsuchenden Felder/Spalten sind Einzelwerte oder Komma-getrennte
        Listen. Mehrere Felder werden zuerst komma-separiert verbunden (CONCAT_WS), dann findet
        eine Listensuche im Ergebnis von CONCAT_WS statt (FIND_IN_SET).
        Beispiel:
            FIND_IN_SET("namedermediendatei",CONCAT_WS(",",titelfoto,quellen)

        Die Abfrage liefert nur die id der betroffenen Sätze. Wenn es keine gibt, wird der gesamte
        Eintrag der Tabelle aus $tabList entfernt, ansonsten wird er durch den späteren Fehlertext
        ersetzt, in dem auch die Liste der gefundenen id auftaucht.

        $tabList kann dann wie es ist als Ergebnis zurückgegeben werden.

    */
    public static function is_in_use( $needle, $fieldtype ) {

        $prefix = rex::getTablePrefix();
        $sql = rex_sql::factory();

        // Relevante Tabellen und Felder ermitteln

        $yform_field = rex_yform_manager_field::table();
        $yform_table = rex_yform_manager_table::table();
        $qry = 'SELECT
                    '.$yform_field.'.table_name AS yformTable,
                    CONCAT('.$yform_table.'.name," (",'.$yform_field.'.table_name,")") AS yformName,
                    GROUP_CONCAT('.$yform_field.'.name) AS yformCol
                FROM
                    '.$yform_table.',
                    '.$yform_field.'
                WHERE
                    '.$yform_table.'.table_name='.$yform_field.'.table_name
                    AND
                    FIND_IN_SET ('.$yform_field.'.type_name,"' . self::$fieldTypeList[$fieldtype] . '")
                GROUP BY
                    '.$yform_field.'.table_name';
        $tabList = $sql->getArray ( $qry );

        // Kommt der Suchbegriff irgendwo vor, wenn ja: wo?
        foreach ($tabList as $k=>&$v)
        {
            $qry = 'SELECT
                        id
                    FROM
                        '.$v['yformTable'].'
                    WHERE
                        FIND_IN_SET("' . $needle . '",CONCAT_WS(",",' . $v['yformCol'] . '))
                    ORDER BY
                        id';
            $idList = $sql->getArray($qry,[],PDO::FETCH_COLUMN);
            if ( empty($idList) )
            {
                unset ($tabList[$k]);
            }
            else
            {
                foreach( $idList as &$id )
                {
                    $url = rex_url::backendController
                            ([
                               'page' => 'yform/manager/data_edit',
                               'table_name' => $v['yformTable'],
                               'data_id' => $id,
                               'func' => 'edit',
                            ]);
                    $id = "<a href=\"$url\">$id</a>";
                }
                $v= '<li>' . $v['yformName'] . ' id: ' . implode(', ',$idList) . '</li>';
            }

        }

        // Warnung zusammenbauen und ausgeben
        if ( $tabList )
        {
            return '<ul>' . implode('',$tabList) . '</ul>';
        }

        return ''; // Null-Meldung

    } // end of is_in_use


    public static function addFieldtypeMedia( $fieldtype )
    {
        self::addFieldtype( 'media', $fieldtype );

    } // end of addFieldtypeMedia


    public static function addFieldtypeArticle( $fieldtype )
    {
        self::addFieldtype( 'article', $fieldtype );

    } // end of addFieldtypeArticle


    public static function addFieldtype( $set, $fieldtype )
    {
        if ( empty( $set ) || empty( $fieldtype ) )
        {
            return;
        }
        $set = strtolower( $set );
        $fieldtype = strtolower( $fieldtype );

        if ( !isset( self::$fieldTypeList[$set] ) )
        {
            self::$fieldTypeList[$set] = $fieldtype;
            return;
        }

        if ( in_array( $fieldtype, explode(',',self::$fieldTypeList[$set]) ) )
        {
            return;
        }

        self::$fieldTypeList[$set] .= ',' . $fieldtype;

    } // end of addFieldtype


}

Grüße
Chris

@dergel dergel modified the milestones: Version 2.3, Version 2.4 Oct 12, 2017
@dergel dergel modified the milestones: Version 2.4, Version 3.0 Nov 24, 2017
@tbaddade
Copy link
Member

tbaddade commented Jan 8, 2018

Ich habe das Prüfen hier integriert.
yakamara/yakme@299bf30

Weitere Infos gibt es in der Readme

@christophboecker
Copy link
Contributor

Jau, Thomas, darauf muss man erst mal kommen: wenn man schon nach API-Start keinen Hook hat einfach den API-Call vorher abwürgen.

Hab verstanden, wo mein Denkfehler lag und diesmal gründlicher nachgrarbeitet. Wäre dennoch sinnvoll, wenn es eine EP "ARTICLE_IS_IN_USE" gäbe :-). Und diesmal mit mehr Testcases gründlicher geprüft.

@christophboecker
Copy link
Contributor

Mit dem Trick könnte man also auch einen EP ARTICLE_IS_IN_USE emulieren. Wär das was für die Trckkiste?

@alxndr-w
Copy link
Contributor

alxndr-w commented May 13, 2019

Kann man das Issue umbenennen in "Medienpool-Dateien schützen"?

@dergel dergel added this to the 3.x milestone May 14, 2019
@skerbis skerbis changed the title yform nutzt nicht mehr den EP … MEDIA_IS_IN_USE? Medienpool-Dateien schützen Jun 11, 2019
@skerbis skerbis changed the title Medienpool-Dateien schützen Feature-Request :: Medienpool-Dateien schützen Jun 11, 2019
@skerbis
Copy link
Contributor Author

skerbis commented Feb 22, 2020

Ping

@christophboecker
Copy link
Contributor

Ja??

@alxndr-w
Copy link
Contributor

pong

@dergel dergel modified the milestones: 3.x, 3.4 Feb 23, 2020
@dergel
Copy link
Member

dergel commented May 15, 2020

@skerbis
Copy link
Contributor Author

skerbis commented May 16, 2020

@dergel dauernd wird auf yakme verwiesen. Warum nicht integrieren?

@dergel
Copy link
Member

dergel commented May 16, 2020

hihi :) . deswegen habe ich mir zur Erinnerung den Link reingelegt .. :) issue ist ja offen inkl Versionszuweisung

dergel added a commit that referenced this issue May 19, 2020
@dergel
Copy link
Member

dergel commented May 19, 2020

sollte alles passen - gerne gegenprüfen.

@dergel dergel closed this as completed May 19, 2020
@skerbis
Copy link
Contributor Author

skerbis commented May 19, 2020

Super! Danke

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants