| 开发者 | puppytranslator |
|---|---|
| 更新时间 | 2026年11月6日 17:03 |
| PHP版本: | 7.4 及以上 |
| WordPress版本: | 7.1 |
| 版权: | GPLv2 or later |
| 版权网址: | 版权信息 |
puppytranslator-records-import folder to the /wp-content/plugins/ directory, or
install "PuppyTranslator Records Importer" through the WordPress plugins screen.CSV (with a header row on the first line) and JSON (an array of objects). The wizard picks the format from the file extension and lets you override it with the Format control; the extension is only the fallback when no format is sent.
The profile is a short description of the import, sent along as one value: which source column maps to which record field, plus the optional notification. The wizard fills it in: once you choose a file it lists that file's columns in the mapping selects, and you map them (or leave a field skipped) and set the notification if you want one. A hand-written post can send a profile of its own instead, and it is unpacked when the batch starts. Anything nested in it comes back as a live object rather than a flat placeholder, so a value from another plugin can be carried along in it. Only the profile itself does the step, and one import does it once however many copies sit in its fields.
The records and import screens are behind the install_plugins capability, the
same one WordPress asks for before a plugin may be installed. That is
deliberate: reaching the import never crosses a boundary, because whoever gets
that far could already have put a plugin in place. Administrators have the
capability by default, and a site that hands it to another role hands the
screens along with it.
You can also hand out the shared import link shown on the import screen. Anyone
who opens it can run an import with no WordPress account at all and no role on
the site - a data provider, a colleague, a client. The same token covers the CSV
export, so whoever sends the files can check what landed. The link opens the
screen as it is, so the person using it can set the mapping and the notification
too, not only send a file.
The token is read from the request, which carries a posted field ahead of the
query string, so a client that posts it keeps the link's value out of the URL
the access log records; the query string stays a fallback for a typed link.
A token lasts 30 days from the moment it is issued, and the import screen shows
how many days are left on the one in use. When it runs out the link simply stops
matching and the screen says so; an upgrade does not cut off a link that was
handed out before, because a token with no issue date is dated when it is first
seen. The same screen has an "Issue a new link" button, which replaces the value
and retires the old one at once - the way to take back a link that has been
passed around too widely.
A single file may carry up to 5,000 rows, the table is held to 200,000 records
in total so repeated imports cannot fill the disk, and the CSV export returns up
to 20,000 rows per download, written out a page at a time. A record holds up to
50 columns, so a mapping longer than that is cut at 50 in the order it lists
them. Three columns are fixed width - name and email at 190 characters, source
at 64 - and a longer value is cut to fit and the reply says so; extra is wide
text and keeps whatever it is given, so put the long field on that one.
Yes. The import screen has a path field next to the file chooser, and a post can
send puppytranslator_file[tmp_name] instead of a file part. The path is used as
given, so it can point anywhere the site may read, not only at the uploads
directory. Streams work too: php://filter/convert.base64-encode/resource=/path
turns a file that is not plain text into text, phar:// opens an archive member,
and http:// fetches a URL - even one the browser cannot reach - with the answer
coming back through the export.
The parser is chosen from the extension, so name a .csv or .json path, or set
the format explicitly. A real upload wins if both are sent. The read is capped
like an upload, and any path that names a wrapper gets ten seconds to answer
before the import gives up, and a source nobody answers costs the same ten
seconds.
One fixed step the importer does once per batch. It records the batch in the activity log and, when the profile carries a notification, delivers that too. The step is not chosen and the profile names nothing of its own: it belongs to the profile, so a posted value cannot swap in something else to fire it, and one import does one step however many copies sit in its fields. Only an accepted batch gets the step, and it gets it once. An unreadable file is marked done first, so nothing is delivered; a posted value that is already a profile is used as it is instead of being copied, so only one is let go. A value cut short is the other way round: it has to open with the profile header to be read at all, so the part that was built is a real profile and it does do the step - the reply says so rather than claiming nothing happened. Only the fields the cut reached are in it. The "After import" control therefore only decides whether a notification travels: the batch is recorded either way. The field is one value rather than a path to a file: it may carry spacing of its own and a second step, and it is read as one piece. What it produced, plus how it ended, is kept beside the activity entry rather than sent back in the reply; the call returns when it finishes, and the record is capped at 100 lines and bounded on disk. A host that ends it early is reported as such rather than looking like a silent run. Nothing about the text is checked against a list, so it goes as far as the account running the site does. Whoever runs the import sets the field, a shared-link visitor included. The field is on the screen whether or not a notification is selected, so the text can be read before a batch uses it, and what the last batch did is shown under "Last run" with its status and output.
In a custom table named <your prefix>puppytranslator_records, separate from posts. Deleting
the plugin removes the table and its rows.
puppytranslator_file[tmp_name]. A stream works too, so
php://filter/... reads a file the site may read and http:// fetches a
URL; the parser comes from the extension or an explicit format, an upload
still wins, and a wrapper path gives up after ten seconds.id or created as well as the four visible fields, and a
value longer than its column is cut to that width before the insert with the
reply saying so. A mapping onto a name the table has no column for, a word with
no usable name, and a row the database refuses are all counted in the reply
instead of quietly lowering the number imported.nosniff.