Ersetzen von mehreren ähnlichen Stellen |
Agi
TEAM - PHP Freak
Dabei seit: 22.11.04
Beiträge: 2.628
Fähigkeiten: WBB3 Profi Forenversion: 3.1
|
|
Hi Leute,
ich habe ein Problem und brauche da ein wenig Hilfe.
Ich habe ein kleines Forum, das sich mit Emulation beschäftigt. Wir möchten aber in naher Zukunft mit einem anderen Forum (das phpBB3 einsetzt) fusionieren.
Die Fusion wird auf Basis von WBB3 stattfinden (weil da der importer schon dabei ist). Allerdings haben wir noch ein paar Extrawünsche, für die der Importer erweitert werden muss.
Bis auf einen haben wir eigentlich alles hinbekommen; aber genau bei diesem Letzten weiß ich überhaupt nicht mehr weiter ...
---
Vorneweg ein paar Abkürzungsdefinitionen, damit ich nicht immer alles ausschreiben muss:
(NR) = Die Nummer des Anhangs in diesem Beitrag (ohne die Klammern rundherum; muss sie nur machen, damit ihr die Abgrenzung merkt)
ID = Die Attachment-ID
UID = Ein spezieller Code, der in phpBB3 verwendet wird (kann man abfragen, der ist also auch vorhanden bzw. bekannt).
---
Das eigentliche Problem:
Im phpBB3 werden Dateianhänge in einem Beitrag so eingetragen:
[attachment=NR:UID]<!-- ia(NR) -->Name.jpg<!-- ia(NR)-->[/attachment:UID]
Damit es im WBB funktioniert, muss das aber geändert werden.
Daher soll das Script
1) Den Namen "Name.jpg" aus diesem String heraustrennen
2) Eine SQL Abfrage starten und die ID abfragen, wo der echte Name "Name.jpg" ist (in der phpBB3 DB)
3) Das ganze [attachment=NR:UID]usw soll durch [attach]ID[/attach] ersetzt werden.
Ich habe es nach langem Hin und Her so hinbekommen, dass das erste Element erfolgreich ersetzt wird; allerdings bleiben alle weiteren Elemente unangetastet.
Und ich wollte nun wissen, was geändert werden muss, damit er diesen Vorgang bei allen [attachment=NR:UID]Name.jpg[/attachment:UID] durchführt.
Ich poste euch auch mal meinen Code (ist leider nicht perfekt, aber ich war auch schon ziemlich müde, da ich über 8h lang probiert habe und da hab ich dann nicht mehr auf Perfektion geachtet - das würde ich noch nachholen, wenn der fertige Code steht):
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
|
<?php
error_reporting(E_ALL);
$ver = mysql_connect('localhost','root','') or die ("Fehler!");
mysql_select_db('db_phpbb3', $ver) or die ("Fehler 2!");
$result = mysql_query("SELECT post_text, bbcode_uid FROM phpbb3_posts WHERE post_id = 41645", $ver);
while ($row = mysql_fetch_array($result)) {
$text = $row['post_text'];
$uid = $row['bbcode_uid'];
}
preg_match_all("/\[attachment=(.+?):".$uid."\]/i", $text, $treffer);
$zahl = count($treffer[1]);
for ($i = 1; $i < $zahl; $i++) {
$i2 = $i-1;
$text = str_replace('[attachment='.$i.':'.$uid.']', '[attach]', $text);
$text = str_replace('[attachment='.$i2.':'.$uid.']', '[attach]', $text);
$text = str_replace('<!-- ia'.$i.' -->', '', $text);
$text = str_replace('<!-- ia'.$i2.' -->', '', $text);
}
$text = str_replace('[/attachment:'.$uid.']', '[/attach]', $text);
preg_match_all("/\[attach\].+?\[\/attach\]/i", $text, $treffer2);
$Name = explode('[attach]', $text);
$Name2 = explode('[/attach]', $Name[1]);
$FileName = $Name2[0];
$sql = "SELECT attach_id
FROM phpbb3_attachments
WHERE real_filename = '".mysql_real_escape_string($FileName)."'";
$result = mysql_query($sql, $ver) OR die(mysql_error());
while ($row = mysql_fetch_array($result)) {
$id = $row['attach_id'];
}
$text = str_replace($FileName, $id, $text);
echo $text.'<br><br>';
mysql_close($ver);
?> |
|
Das ergibt dann zum Beispiel:
Zitat: |
Hm, aber die Diskusion macht dich Spaß xD STimmt eigentlich... [attach]135300[/attach] Test [attach]vogel_03.jpg[/attach] Test2 ^^ |
Ich würde mich sehr freuen, wenn ihr mir helfen könntet, da dieser Teil sehr wichtig für uns ist und ich wie gesagt mit meinem Latein am Ende bin.
__________________
|
|
21.04.09 00:55 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Das solltest du wenn du schon im WBB3 arbeitest mit einer WorkerAction machen. Da attachments erst nach den posts importiert werden kann man leider das Ganze nicht schon beim Import erledigen. Man könnte sich zwar per EL reinhängen, aber ich hab gerade keine Lust alle Konsequenzen abzuschätzen
Hier mal ein Blindansatz als UpdateCounter Action (musst sie noch per EL dem WBB bekannt machen).
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
|
<?php
require_once(WBB_DIR.'lib/acp/action/UpdateCounterAction.class.php');
require_once(WCF_DIR.'lib/data/message/attachment/Attachments.class.php');
class UpdatePHPBB3AttachmentsAction extends UpdateCounterAction {
public $action = 'UpdatePHPBB3Attachments';
/**
* @see Action::execute()
*/
public function execute() {
parent::execute();
// count posts
$sql = "SELECT COUNT(*) AS count
FROM wbb".WBB_N."_post
WHERE attachments > 0";
$row = WCF::getDB()->getFirstRow($sql);
$count = $row['count'];
// get postids
$postIDs = '';
$sql = "SELECT postID
FROM wbb".WBB_N."_post
ORDER BY postID";
$result = WCF::getDB()->sendQuery($sql, $this->limit, ($this->limit * $this->loop));
while ($row = WCF::getDB()->fetchArray($result)) {
$postIDs .= ','.$row['postID'];
}
if (empty($postIDs)) {
$this->calcProgress();
$this->finish();
}
// get attachments
$attachments = new Attachments($postIDs);
// get post messages
$sql = "SELECT postID, message wbb".WBB_N."_post
WHERE post.postID IN (0".$postIDs.")";
$result = WCF::getDB()->sendQuery($sql);
while ($row = WCF::getDB()->fetchArray($result)) {
$postAttachments = $attachments->getAttachments($row['postID']);
if (!count($postAttachments)) continue;
$message = $row['message'];
preg_match_all('/\[attachment=\d*:\d*\]<!--.*?-->(.*)<!--.*/is', $message, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$filename = $match[1];
foreach ($postAttachments as $postAttachment) {
if ($postAttachment['attachmentName'] == $filename) {
preg_replace('/\[attachment.*\].*?('.$filename.').*?\[\/attachment.*\]/is', '[attach]'.$postAttachment['attachmentID'].'[/attach]', $message);
continue 2;
}
}
}
$sql = "UPDATE wbb".WBB_N."_post
SET message = '".escapeString($message)."'
WHERE postID = ".$row['postID'];
WCF::getDB()->sendQuery($sql);
// clear post cache
$sql = "DELETE FROM wbb".WBB_N."_post_cache
WHERE postID = ".$row['postID'];
WCF::getDB()->sendQuery($sql);
}
$this->executed();
$this->calcProgress(($this->limit * $this->loop), $count);
$this->nextLoop();
}
}
?>
|
|
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Hawkes: 21.04.09 10:10.
|
|
21.04.09 10:06 |
Finden
Als Freund hinzufügen
|
|
Agi
TEAM - PHP Freak
Dabei seit: 22.11.04
Beiträge: 2.628
Fähigkeiten: WBB3 Profi Forenversion: 3.1
Themenstarter
|
|
Hi, vielen Dank für deie Mühen. Sry dass ich erst jetzt antworte, war die letzte Zeit beschäftigt.
Ich habs eingebunden und auch ein klein wenig ändern müssen, weil sonst ein SQL Fehler kam (entweder beim Auslesen der Attachments oder beim Auslesen der Posts).
Nun läuft das Script durch, allerdings gibt es 2 Probleme:
1. Problem: Die Prozentanzeige wird astronomisch hoch (läuft aber durch, bis fertig ist). Nach Abschluss hat er soviel Prozent: 111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111111111111111111
111111112222222222222222222222222222222222222222222222222222222222222222222
222222222222222222222222222222222222222222222222222222222222222222222222222
222222222222222333333333333333333333333333333333333333333333333333333333333
333333333333333333333333333333333333333333333333333333333333333333333333333
333333333333333333333334444444444444444444444444444444444444444444444444444
444444444444444444444444444444444444444444444444444444444444444444444444444
444444444444444444444444100%
2. Problem: Das Script aktualisiert leider nicht alles. Wenn jetzt nur ein Attachment im Post ist, wird es problemlos umgewandelt.
Wenn aber mehrere Anhänge im Beitrag eingebunden wurden, lässt er diese unverändert.
---
Hier nochmal die Version vom Script die ich benutze:
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
|
<?php
require_once(WBB_DIR.'lib/acp/action/UpdateCounterAction.class.php');
require_once(WCF_DIR.'lib/data/message/attachment/Attachments.class.php');
class UpdatePhpbb3attachmentsAction extends UpdateCounterAction {
public $action = 'UpdatePhpbb3attachments';
/**
* @see Action::execute()
*/
public function execute() {
parent::execute();
// count posts
$sql = "SELECT COUNT(*) AS count
FROM wbb".WBB_N."_post
WHERE attachments > 0";
$row = WCF::getDB()->getFirstRow($sql);
$count = $row['count'];
// get postids
$postIDs = 0;
$sql = "SELECT postID
FROM wbb".WBB_N."_post
ORDER BY postID";
$result = WCF::getDB()->sendQuery($sql, $this->limit, ($this->limit * $this->loop));
while ($row = WCF::getDB()->fetchArray($result)) {
$postIDsAttach .= ','.$row['postID'];
$postIDs .= ','.$row['postID'];
}
if (empty($postIDs)) {
$this->calcProgress();
$this->finish();
}
// get attachments
$attachments = new Attachments($postIDs);
// get post messages
$sql = "SELECT postID, message
FROM wbb".WBB_N."_post
WHERE postID IN (".$postIDs.")";
$result = WCF::getDB()->sendQuery($sql);
while ($row = WCF::getDB()->fetchArray($result)) {
$postAttachments = $attachments->getAttachments($row['postID']);
if (!count($postAttachments)) continue;
$message = $row['message'];
preg_match_all('/\[attachment=\d*\]<!--.*?-->(.*)<!--.*/is', $message, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$filename = $match[1];
foreach ($postAttachments as $postAttachment) {
if ($postAttachment['attachmentName'] == $filename) {
$message = preg_replace('/\[attachment.*\].*?('.$filename.').*?\[\/attachment.*\]/is', '[attach]'.$postAttachment['attachmentID'].'[/attach]', $message);
continue 2;
}
}
}
$sql = "UPDATE wbb".WBB_N."_post
SET message = '".escapeString($message)."'
WHERE postID = ".$row['postID'];
WCF::getDB()->sendQuery($sql);
// clear post cache
$sql = "DELETE FROM wbb".WBB_N."_post_cache
WHERE postID = ".$row['postID'];
WCF::getDB()->sendQuery($sql);
}
$this->executed();
$this->calcProgress(($this->limit * $this->loop), $count);
$this->nextLoop();
}
}
?> |
|
__________________
|
|
22.04.09 23:20 |
Finden
Als Freund hinzufügen
|
|
Hawkes
gesperrt 10/01/10
Dabei seit: 31.03.04
Beiträge: 213
|
|
Teste mal das RegEx aus dem preg_match_all auf so einen post, wie viele Indizes dort das array hat. $matches sollte eigentlich soviele subarrays wie attachments in einem post haben und mit continue 2 sollte ich ja nur die beiden forschleifen um 1 weiter laufen lassen.
Zu der astronomischen Zahl: Was für ein limit hast du denn gesetzt? Irgendwie berechnet er den Prozess falsch.
Das Script hab ich wie gesagt blind geschrieben, ohne auch nur irgendwas zu testen. Bin froh, dass da jetzt überhaupt was geht
PS: Wenn du das fertig hast, könntest du es vielleicht als Plugin veröffentlichen. Denke da hätten eventuell manche Interesse dran.
|
|
22.04.09 23:29 |
Finden
Als Freund hinzufügen
|
|
Agi
TEAM - PHP Freak
Dabei seit: 22.11.04
Beiträge: 2.628
Fähigkeiten: WBB3 Profi Forenversion: 3.1
Themenstarter
|
|
Zitat: |
Teste mal das RegEx aus dem preg_match_all auf so einen post, wie viele Indizes dort das array hat. $matches sollte eigentlich soviele subarrays wie attachments in einem post haben und mit continue 2 sollte ich ja nur die beiden forschleifen um 1 weiter laufen lassen. |
Hmm, $matches ist leer. Es ändert sich auch nichts, wenn ich das RegEx aus preg_match_all einsetze.
Ersetzt wird anscheinend nur, wenn sich nur ein Attachment im Beitrag befindet (all diese sind korrekt ersetzt). Wenn mehr als eines drinnen ist, wird es ignoriert.
Limit hab ich 50 eingestellt. Allerdings ändert sich auch nichts, wenn ich 100 oder 500 einstelle; nur halt, dass die astronomische Zahl schneller erreicht wird.
Zitat: |
PS: Wenn du das fertig hast, könntest du es vielleicht als Plugin veröffentlichen. Denke da hätten eventuell manche Interesse dran. |
Werd ich mir überlegen. Sofern wir es so hinbekommen, dass es auch korrekt funktioniert. ^^ Evtl. zusammen mit ein paar anderen Erweiterungen/Updates für den PHPBB3 Importer (da dort noch ein paar Fehler drinnen waren, die ich ausgebügelt habe).
Naja, mal sehen.
//Edit:
Mit folgendem Script ersetzt er jetzt auch, wenn mehr als 1 Attachment im Beitrag ist. Allerdings ersetzt er scheinbar nur das Erste und alle Anderen verschwinden einfach gänzlich. ^^"
php: |
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
|
<?php
require_once(WBB_DIR.'lib/acp/action/UpdateCounterAction.class.php');
require_once(WCF_DIR.'lib/data/message/attachment/Attachments.class.php');
class UpdatePhpbb3attachmentsAction extends UpdateCounterAction {
public $action = 'UpdatePhpbb3attachments';
/**
* @see Action::execute()
*/
public function execute() {
parent::execute();
// count posts
$sql = "SELECT COUNT(*) AS count
FROM wbb".WBB_N."_post
WHERE attachments > 0";
$row = WCF::getDB()->getFirstRow($sql);
$count = $row['count'];
// get postids
$postIDs = '';
$postIDsAttach = 0;
$sql = "SELECT postID
FROM wbb".WBB_N."_post
ORDER BY postID";
$result = WCF::getDB()->sendQuery($sql, $this->limit, ($this->limit * $this->loop));
while ($row = WCF::getDB()->fetchArray($result)) {
$postIDsAttach .= ','.$row['postID'];
$postIDs .= ','.$row['postID'];
}
if (empty($postIDs)) {
$this->calcProgress();
$this->finish();
}
// get attachments
$attachments = new Attachments($postIDsAttach);
// get post messages
$sql = "SELECT postID, message
FROM wbb".WBB_N."_post
WHERE postID IN (0".$postIDs.")";
$result = WCF::getDB()->sendQuery($sql);
while ($row = WCF::getDB()->fetchArray($result)) {
$postAttachments = $attachments->getAttachments($row['postID']);
if (!count($postAttachments)) continue;
$message = $row['message'];
preg_match_all('/\[attachment=.*\]<!-- ia.*? -->(.*)<!-- ia.*?/is', $message, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$filename = $match[1];
foreach ($postAttachments as $postAttachment) {
if ($postAttachment['attachmentName'] == $filename) {
$message = preg_replace('/\[attachment=.*\]<!-- ia.*? -->(.*)<!-- ia.*? -->\[\/attachment\]/is', '[attach]'.$postAttachment['attachmentID'].'[/attach]', $message);
continue 2;
}
}
}
$sql = "UPDATE wbb".WBB_N."_post
SET message = '".escapeString($message)."'
WHERE postID = ".$row['postID'];
WCF::getDB()->sendQuery($sql);
// clear post cache
$sql = "DELETE FROM wbb".WBB_N."_post_cache
WHERE postID = ".$row['postID'];
WCF::getDB()->sendQuery($sql);
}
$this->executed();
$this->calcProgress(($this->limit * $this->loop), $count);
$this->nextLoop();
}
}
?> |
|
__________________
|
|
23.04.09 15:59 |
Finden
Als Freund hinzufügen
|
|
|